Skip to content

Commit 75726ca

Browse files
committed
Auto merge of rust-lang#112629 - compiler-errors:atb-imply, r=jackh726
Make associated type bounds in supertrait position implied `trait A: B<Assoc: C> {}` should be able to imply both `Self: B` and `<Self as B>::Assoc: C`. Adjust the way that we collect implied predicates to do so. Fixes rust-lang#112573 Fixes rust-lang#112568
2 parents 5bd28f5 + de0e7d3 commit 75726ca

File tree

7 files changed

+142
-101
lines changed

7 files changed

+142
-101
lines changed

compiler/rustc_hir_analysis/src/astconv/bounds.rs

+27-35
Original file line numberDiff line numberDiff line change
@@ -9,12 +9,12 @@ use rustc_span::symbol::Ident;
99
use rustc_span::{ErrorGuaranteed, Span};
1010
use rustc_trait_selection::traits;
1111

12-
use crate::astconv::{AstConv, ConvertedBinding, ConvertedBindingKind};
12+
use crate::astconv::{
13+
AstConv, ConvertedBinding, ConvertedBindingKind, OnlySelfBounds, PredicateFilter,
14+
};
1315
use crate::bounds::Bounds;
1416
use crate::errors::{MultipleRelaxedDefaultBounds, ValueOfAssociatedStructAlreadySpecified};
1517

16-
use super::OnlySelfBounds;
17-
1818
impl<'tcx> dyn AstConv<'tcx> + '_ {
1919
/// Sets `implicitly_sized` to true on `Bounds` if necessary
2020
pub(crate) fn add_implicitly_sized(
@@ -176,47 +176,39 @@ impl<'tcx> dyn AstConv<'tcx> + '_ {
176176
&self,
177177
param_ty: Ty<'tcx>,
178178
ast_bounds: &[hir::GenericBound<'_>],
179-
only_self_bounds: OnlySelfBounds,
179+
filter: PredicateFilter,
180180
) -> Bounds<'tcx> {
181181
let mut bounds = Bounds::default();
182-
self.add_bounds(
183-
param_ty,
184-
ast_bounds.iter(),
185-
&mut bounds,
186-
ty::List::empty(),
187-
only_self_bounds,
188-
);
189-
debug!(?bounds);
190182

191-
bounds
192-
}
193-
194-
/// Convert the bounds in `ast_bounds` that refer to traits which define an associated type
195-
/// named `assoc_name` into ty::Bounds. Ignore the rest.
196-
pub(crate) fn compute_bounds_that_match_assoc_item(
197-
&self,
198-
param_ty: Ty<'tcx>,
199-
ast_bounds: &[hir::GenericBound<'_>],
200-
assoc_name: Ident,
201-
) -> Bounds<'tcx> {
202-
let mut result = Vec::new();
203-
204-
for ast_bound in ast_bounds {
205-
if let Some(trait_ref) = ast_bound.trait_ref()
206-
&& let Some(trait_did) = trait_ref.trait_def_id()
207-
&& self.tcx().trait_may_define_assoc_item(trait_did, assoc_name)
208-
{
209-
result.push(ast_bound.clone());
183+
let only_self_bounds = match filter {
184+
PredicateFilter::All | PredicateFilter::SelfAndAssociatedTypeBounds => {
185+
OnlySelfBounds(false)
210186
}
211-
}
187+
PredicateFilter::SelfOnly | PredicateFilter::SelfThatDefines(_) => OnlySelfBounds(true),
188+
};
212189

213-
let mut bounds = Bounds::default();
214190
self.add_bounds(
215191
param_ty,
216-
result.iter(),
192+
ast_bounds.iter().filter(|bound| {
193+
match filter {
194+
PredicateFilter::All
195+
| PredicateFilter::SelfOnly
196+
| PredicateFilter::SelfAndAssociatedTypeBounds => true,
197+
PredicateFilter::SelfThatDefines(assoc_name) => {
198+
if let Some(trait_ref) = bound.trait_ref()
199+
&& let Some(trait_did) = trait_ref.trait_def_id()
200+
&& self.tcx().trait_may_define_assoc_item(trait_did, assoc_name)
201+
{
202+
true
203+
} else {
204+
false
205+
}
206+
}
207+
}
208+
}),
217209
&mut bounds,
218210
ty::List::empty(),
219-
OnlySelfBounds(true),
211+
only_self_bounds,
220212
);
221213
debug!(?bounds);
222214

compiler/rustc_hir_analysis/src/astconv/mod.rs

+18
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,24 @@ pub struct PathSeg(pub DefId, pub usize);
5858
#[derive(Copy, Clone, Debug)]
5959
pub struct OnlySelfBounds(pub bool);
6060

61+
#[derive(Copy, Clone, Debug)]
62+
pub enum PredicateFilter {
63+
/// All predicates may be implied by the trait.
64+
All,
65+
66+
/// Only traits that reference `Self: ..` are implied by the trait.
67+
SelfOnly,
68+
69+
/// Only traits that reference `Self: ..` and define an associated type
70+
/// with the given ident are implied by the trait.
71+
SelfThatDefines(Ident),
72+
73+
/// Only traits that reference `Self: ..` and their associated type bounds.
74+
/// For example, given `Self: Tr<A: B>`, this would expand to `Self: Tr`
75+
/// and `<Self as Tr>::A: B`.
76+
SelfAndAssociatedTypeBounds,
77+
}
78+
6179
pub trait AstConv<'tcx> {
6280
fn tcx(&self) -> TyCtxt<'tcx>;
6381

compiler/rustc_hir_analysis/src/collect/item_bounds.rs

+3-3
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
use super::ItemCtxt;
2-
use crate::astconv::{AstConv, OnlySelfBounds};
2+
use crate::astconv::{AstConv, PredicateFilter};
33
use rustc_hir as hir;
44
use rustc_infer::traits::util;
55
use rustc_middle::ty::subst::InternalSubsts;
@@ -26,7 +26,7 @@ fn associated_type_bounds<'tcx>(
2626
);
2727

2828
let icx = ItemCtxt::new(tcx, assoc_item_def_id);
29-
let mut bounds = icx.astconv().compute_bounds(item_ty, ast_bounds, OnlySelfBounds(false));
29+
let mut bounds = icx.astconv().compute_bounds(item_ty, ast_bounds, PredicateFilter::All);
3030
// Associated types are implicitly sized unless a `?Sized` bound is found
3131
icx.astconv().add_implicitly_sized(&mut bounds, item_ty, ast_bounds, None, span);
3232

@@ -68,7 +68,7 @@ fn opaque_type_bounds<'tcx>(
6868
) -> &'tcx [(ty::Clause<'tcx>, Span)] {
6969
ty::print::with_no_queries!({
7070
let icx = ItemCtxt::new(tcx, opaque_def_id);
71-
let mut bounds = icx.astconv().compute_bounds(item_ty, ast_bounds, OnlySelfBounds(false));
71+
let mut bounds = icx.astconv().compute_bounds(item_ty, ast_bounds, PredicateFilter::All);
7272
// Opaque types are implicitly sized unless a `?Sized` bound is found
7373
icx.astconv().add_implicitly_sized(&mut bounds, item_ty, ast_bounds, None, span);
7474
debug!(?bounds);

compiler/rustc_hir_analysis/src/collect/predicates_of.rs

+36-63
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
use crate::astconv::{AstConv, OnlySelfBounds};
1+
use crate::astconv::{AstConv, OnlySelfBounds, PredicateFilter};
22
use crate::bounds::Bounds;
33
use crate::collect::ItemCtxt;
44
use crate::constrained_generic_params as cgp;
@@ -125,7 +125,7 @@ fn gather_explicit_predicates_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::Gen
125125
if let Some(self_bounds) = is_trait {
126126
predicates.extend(
127127
icx.astconv()
128-
.compute_bounds(tcx.types.self_param, self_bounds, OnlySelfBounds(false))
128+
.compute_bounds(tcx.types.self_param, self_bounds, PredicateFilter::All)
129129
.clauses(),
130130
);
131131
}
@@ -530,19 +530,6 @@ pub(super) fn explicit_predicates_of<'tcx>(
530530
}
531531
}
532532

533-
#[derive(Copy, Clone, Debug)]
534-
pub enum PredicateFilter {
535-
/// All predicates may be implied by the trait
536-
All,
537-
538-
/// Only traits that reference `Self: ..` are implied by the trait
539-
SelfOnly,
540-
541-
/// Only traits that reference `Self: ..` and define an associated type
542-
/// with the given ident are implied by the trait
543-
SelfThatDefines(Ident),
544-
}
545-
546533
/// Ensures that the super-predicates of the trait with a `DefId`
547534
/// of `trait_def_id` are converted and stored. This also ensures that
548535
/// the transitive super-predicates are converted.
@@ -564,11 +551,15 @@ pub(super) fn implied_predicates_of(
564551
tcx: TyCtxt<'_>,
565552
trait_def_id: LocalDefId,
566553
) -> ty::GenericPredicates<'_> {
567-
if tcx.is_trait_alias(trait_def_id.to_def_id()) {
568-
implied_predicates_with_filter(tcx, trait_def_id.to_def_id(), PredicateFilter::All)
569-
} else {
570-
tcx.super_predicates_of(trait_def_id)
571-
}
554+
implied_predicates_with_filter(
555+
tcx,
556+
trait_def_id.to_def_id(),
557+
if tcx.is_trait_alias(trait_def_id.to_def_id()) {
558+
PredicateFilter::All
559+
} else {
560+
PredicateFilter::SelfAndAssociatedTypeBounds
561+
},
562+
)
572563
}
573564

574565
/// Ensures that the super-predicates of the trait with a `DefId`
@@ -601,44 +592,14 @@ pub(super) fn implied_predicates_with_filter(
601592
let icx = ItemCtxt::new(tcx, trait_def_id);
602593

603594
let self_param_ty = tcx.types.self_param;
604-
let (superbounds, where_bounds_that_match) = match filter {
605-
PredicateFilter::All => (
606-
// Convert the bounds that follow the colon (or equal in trait aliases)
607-
icx.astconv().compute_bounds(self_param_ty, bounds, OnlySelfBounds(false)),
608-
// Also include all where clause bounds
609-
icx.type_parameter_bounds_in_generics(
610-
generics,
611-
item.owner_id.def_id,
612-
self_param_ty,
613-
OnlySelfBounds(false),
614-
None,
615-
),
616-
),
617-
PredicateFilter::SelfOnly => (
618-
// Convert the bounds that follow the colon (or equal in trait aliases)
619-
icx.astconv().compute_bounds(self_param_ty, bounds, OnlySelfBounds(true)),
620-
// Include where clause bounds for `Self`
621-
icx.type_parameter_bounds_in_generics(
622-
generics,
623-
item.owner_id.def_id,
624-
self_param_ty,
625-
OnlySelfBounds(true),
626-
None,
627-
),
628-
),
629-
PredicateFilter::SelfThatDefines(assoc_name) => (
630-
// Convert the bounds that follow the colon (or equal) that reference the associated name
631-
icx.astconv().compute_bounds_that_match_assoc_item(self_param_ty, bounds, assoc_name),
632-
// Include where clause bounds for `Self` that reference the associated name
633-
icx.type_parameter_bounds_in_generics(
634-
generics,
635-
item.owner_id.def_id,
636-
self_param_ty,
637-
OnlySelfBounds(true),
638-
Some(assoc_name),
639-
),
640-
),
641-
};
595+
let superbounds = icx.astconv().compute_bounds(self_param_ty, bounds, filter);
596+
597+
let where_bounds_that_match = icx.type_parameter_bounds_in_generics(
598+
generics,
599+
item.owner_id.def_id,
600+
self_param_ty,
601+
filter,
602+
);
642603

643604
// Combine the two lists to form the complete set of superbounds:
644605
let implied_bounds =
@@ -743,8 +704,7 @@ pub(super) fn type_param_predicates(
743704
ast_generics,
744705
def_id,
745706
ty,
746-
OnlySelfBounds(true),
747-
Some(assoc_name),
707+
PredicateFilter::SelfThatDefines(assoc_name),
748708
)
749709
.into_iter()
750710
.filter(|(predicate, _)| match predicate.kind().skip_binder() {
@@ -768,8 +728,7 @@ impl<'tcx> ItemCtxt<'tcx> {
768728
ast_generics: &'tcx hir::Generics<'tcx>,
769729
param_def_id: LocalDefId,
770730
ty: Ty<'tcx>,
771-
only_self_bounds: OnlySelfBounds,
772-
assoc_name: Option<Ident>,
731+
filter: PredicateFilter,
773732
) -> Vec<(ty::Clause<'tcx>, Span)> {
774733
let mut bounds = Bounds::default();
775734

@@ -778,9 +737,23 @@ impl<'tcx> ItemCtxt<'tcx> {
778737
continue;
779738
};
780739

740+
let (only_self_bounds, assoc_name) = match filter {
741+
PredicateFilter::All | PredicateFilter::SelfAndAssociatedTypeBounds => {
742+
(OnlySelfBounds(false), None)
743+
}
744+
PredicateFilter::SelfOnly => (OnlySelfBounds(true), None),
745+
PredicateFilter::SelfThatDefines(assoc_name) => {
746+
(OnlySelfBounds(true), Some(assoc_name))
747+
}
748+
};
749+
750+
// Subtle: If we're collecting `SelfAndAssociatedTypeBounds`, then we
751+
// want to only consider predicates with `Self: ...`, but we don't want
752+
// `OnlySelfBounds(true)` since we want to collect the nested associated
753+
// type bound as well.
781754
let bound_ty = if predicate.is_param_bound(param_def_id.to_def_id()) {
782755
ty
783-
} else if !only_self_bounds.0 {
756+
} else if matches!(filter, PredicateFilter::All) {
784757
self.to_ty(predicate.bounded_ty)
785758
} else {
786759
continue;
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
// check-pass
2+
3+
#![feature(associated_type_bounds)]
4+
5+
trait Trait: Super<Assoc: Bound> {}
6+
7+
trait Super {
8+
type Assoc;
9+
}
10+
11+
trait Bound {}
12+
13+
fn foo<T>(x: T)
14+
where
15+
T: Trait,
16+
{
17+
}
18+
19+
fn main() {}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
// edition:2021
2+
// check-pass
3+
4+
#![feature(async_fn_in_trait, return_position_impl_trait_in_trait, return_type_notation)]
5+
//~^ WARN the feature `return_type_notation` is incomplete
6+
7+
use std::future::Future;
8+
9+
struct JoinHandle<T>(fn() -> T);
10+
11+
fn spawn<T>(_: impl Future<Output = T>) -> JoinHandle<T> {
12+
todo!()
13+
}
14+
15+
trait Foo {
16+
async fn bar(&self) -> i32;
17+
}
18+
19+
trait SendFoo: Foo<bar(): Send> + Send {}
20+
21+
fn foobar(foo: impl SendFoo) -> JoinHandle<i32> {
22+
spawn(async move {
23+
let future = foo.bar();
24+
future.await
25+
})
26+
}
27+
28+
fn main() {}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
warning: the feature `return_type_notation` is incomplete and may not be safe to use and/or cause compiler crashes
2+
--> $DIR/rtn-implied-in-supertrait.rs:4:68
3+
|
4+
LL | #![feature(async_fn_in_trait, return_position_impl_trait_in_trait, return_type_notation)]
5+
| ^^^^^^^^^^^^^^^^^^^^
6+
|
7+
= note: see issue #109417 <https://github.com/rust-lang/rust/issues/109417> for more information
8+
= note: `#[warn(incomplete_features)]` on by default
9+
10+
warning: 1 warning emitted
11+

0 commit comments

Comments
 (0)