Skip to content

Commit 362010d

Browse files
committed
Auto merge of #96715 - cjgillot:trait-alias-loop, r=compiler-errors
Fortify handing of where bounds on trait & trait alias definitions Closes #96664 Closes #96665 Since #93803, when listing all bounds and predicates we now need to account for the possible presence of predicates on any of the generic parameters. Both bugs were hidden by the special handling of bounds at the generic parameter declaration position. Trait alias expansion used to confuse predicates on `Self` and where predicates. Exiting too late when listing all the bounds caused a cycle error.
2 parents cb39073 + e947fad commit 362010d

File tree

10 files changed

+69
-20
lines changed

10 files changed

+69
-20
lines changed

compiler/rustc_error_messages/locales/en-US/typeck.ftl

+1
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,7 @@ typeck-copy-impl-on-non-adt =
4545
4646
typeck-trait-object-declared-with-no-traits =
4747
at least one trait is required for an object type
48+
.alias-span = this alias does not contain a trait
4849
4950
typeck-ambiguous-lifetime-bound =
5051
ambiguous lifetime bound, explicit lifetime bound required

compiler/rustc_trait_selection/src/traits/util.rs

+2-1
Original file line numberDiff line numberDiff line change
@@ -118,13 +118,14 @@ impl<'tcx> TraitAliasExpander<'tcx> {
118118

119119
// Get components of trait alias.
120120
let predicates = tcx.super_predicates_of(trait_ref.def_id());
121+
debug!(?predicates);
121122

122123
let items = predicates.predicates.iter().rev().filter_map(|(pred, span)| {
123124
pred.subst_supertrait(tcx, &trait_ref)
124125
.to_opt_poly_trait_pred()
125126
.map(|trait_ref| item.clone_and_push(trait_ref.map_bound(|t| t.trait_ref), *span))
126127
});
127-
debug!("expand_trait_aliases: items={:?}", items.clone());
128+
debug!("expand_trait_aliases: items={:?}", items.clone().collect::<Vec<_>>());
128129

129130
self.stack.extend(items);
130131

compiler/rustc_typeck/src/astconv/mod.rs

+11-3
Original file line numberDiff line numberDiff line change
@@ -1064,6 +1064,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
10641064
let mut bounds = Bounds::default();
10651065

10661066
self.add_bounds(param_ty, ast_bounds.iter(), &mut bounds, ty::List::empty());
1067+
debug!(?bounds);
10671068

10681069
bounds
10691070
}
@@ -1327,8 +1328,9 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
13271328
// is used and no 'maybe' bounds are used.
13281329
let expanded_traits =
13291330
traits::expand_trait_aliases(tcx, bounds.trait_bounds.iter().map(|&(a, b, _)| (a, b)));
1330-
let (mut auto_traits, regular_traits): (Vec<_>, Vec<_>) =
1331-
expanded_traits.partition(|i| tcx.trait_is_auto(i.trait_ref().def_id()));
1331+
let (mut auto_traits, regular_traits): (Vec<_>, Vec<_>) = expanded_traits
1332+
.filter(|i| i.trait_ref().self_ty().skip_binder() == dummy_self)
1333+
.partition(|i| tcx.trait_is_auto(i.trait_ref().def_id()));
13321334
if regular_traits.len() > 1 {
13331335
let first_trait = &regular_traits[0];
13341336
let additional_trait = &regular_traits[1];
@@ -1362,7 +1364,13 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
13621364
}
13631365

13641366
if regular_traits.is_empty() && auto_traits.is_empty() {
1365-
tcx.sess.emit_err(TraitObjectDeclaredWithNoTraits { span });
1367+
let trait_alias_span = bounds
1368+
.trait_bounds
1369+
.iter()
1370+
.map(|&(trait_ref, _, _)| trait_ref.def_id())
1371+
.find(|&trait_ref| tcx.is_trait_alias(trait_ref))
1372+
.map(|trait_ref| tcx.def_span(trait_ref));
1373+
tcx.sess.emit_err(TraitObjectDeclaredWithNoTraits { span, trait_alias_span });
13661374
return tcx.ty_error();
13671375
}
13681376

compiler/rustc_typeck/src/collect.rs

+8-5
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,7 @@ use std::iter;
5252
mod item_bounds;
5353
mod type_of;
5454

55+
#[derive(Debug)]
5556
struct OnlySelfBounds(bool);
5657

5758
///////////////////////////////////////////////////////////////////////////
@@ -650,6 +651,7 @@ impl<'tcx> ItemCtxt<'tcx> {
650651
/// AST. We do this to avoid having to convert *all* the bounds, which
651652
/// would create artificial cycles. Instead, we can only convert the
652653
/// bounds for a type parameter `X` if `X::Foo` is used.
654+
#[instrument(level = "trace", skip(self, ast_generics))]
653655
fn type_parameter_bounds_in_generics(
654656
&self,
655657
ast_generics: &'tcx hir::Generics<'tcx>,
@@ -659,6 +661,7 @@ impl<'tcx> ItemCtxt<'tcx> {
659661
assoc_name: Option<Ident>,
660662
) -> Vec<(ty::Predicate<'tcx>, Span)> {
661663
let param_def_id = self.tcx.hir().local_def_id(param_id).to_def_id();
664+
debug!(?param_def_id);
662665
ast_generics
663666
.predicates
664667
.iter()
@@ -676,13 +679,12 @@ impl<'tcx> ItemCtxt<'tcx> {
676679
};
677680
let bvars = self.tcx.late_bound_vars(bp.bounded_ty.hir_id);
678681

679-
bp.bounds
680-
.iter()
681-
.filter(|b| match assoc_name {
682+
bp.bounds.iter().filter_map(move |b| bt.map(|bt| (bt, b, bvars))).filter(
683+
|(_, b, _)| match assoc_name {
682684
Some(assoc_name) => self.bound_defines_assoc_item(b, assoc_name),
683685
None => true,
684-
})
685-
.filter_map(move |b| bt.map(|bt| (bt, b, bvars)))
686+
},
687+
)
686688
})
687689
.flat_map(|(bt, b, bvars)| predicates_from_bound(self, bt, b, bvars))
688690
.collect()
@@ -1140,6 +1142,7 @@ fn super_predicates_that_define_assoc_type(
11401142

11411143
// Combine the two lists to form the complete set of superbounds:
11421144
let superbounds = &*tcx.arena.alloc_from_iter(superbounds1.into_iter().chain(superbounds2));
1145+
debug!(?superbounds);
11431146

11441147
// Now require that immediate supertraits are converted,
11451148
// which will, in turn, reach indirect supertraits.

compiler/rustc_typeck/src/errors.rs

+2
Original file line numberDiff line numberDiff line change
@@ -103,6 +103,8 @@ pub struct CopyImplOnNonAdt {
103103
pub struct TraitObjectDeclaredWithNoTraits {
104104
#[primary_span]
105105
pub span: Span,
106+
#[label = "alias-span"]
107+
pub trait_alias_span: Option<Span>,
106108
}
107109

108110
#[derive(SessionDiagnostic)]

src/test/ui/traits/alias/only-maybe-bound.stderr

+6
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,18 @@
11
error[E0224]: at least one trait is required for an object type
22
--> $DIR/only-maybe-bound.rs:13:12
33
|
4+
LL | trait _1 = _0;
5+
| -------------- this alias does not contain a trait
6+
...
47
LL | type _T0 = dyn _1;
58
| ^^^^^^
69

710
error[E0224]: at least one trait is required for an object type
811
--> $DIR/only-maybe-bound.rs:19:12
912
|
13+
LL | trait _2 = _1 + _1;
14+
| ------------------- this alias does not contain a trait
15+
LL |
1016
LL | type _T1 = dyn _2;
1117
| ^^^^^^
1218

src/test/ui/traits/issue-65673.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,6 @@ trait Alias<T> = where T: Trait;
77

88
impl<T> WithType for T {
99
type Ctx = dyn Alias<T>;
10-
//~^ ERROR the size for values of type `(dyn Trait + 'static)` cannot be known at compilation time
10+
//~^ ERROR at least one trait is required for an object type [E0224]
1111
}
1212
fn main() {}

src/test/ui/traits/issue-65673.stderr

+6-10
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,12 @@
1-
error[E0277]: the size for values of type `(dyn Trait + 'static)` cannot be known at compilation time
1+
error[E0224]: at least one trait is required for an object type
22
--> $DIR/issue-65673.rs:9:16
33
|
4+
LL | trait Alias<T> = where T: Trait;
5+
| -------------------------------- this alias does not contain a trait
6+
...
47
LL | type Ctx = dyn Alias<T>;
5-
| ^^^^^^^^^^^^ doesn't have a size known at compile-time
6-
|
7-
= help: the trait `Sized` is not implemented for `(dyn Trait + 'static)`
8-
note: required by a bound in `WithType::Ctx`
9-
--> $DIR/issue-65673.rs:4:5
10-
|
11-
LL | type Ctx;
12-
| ^^^^^^^^^ required by this bound in `WithType::Ctx`
8+
| ^^^^^^^^^^^^
139

1410
error: aborting due to previous error
1511

16-
For more information about this error, try `rustc --explain E0277`.
12+
For more information about this error, try `rustc --explain E0224`.

src/test/ui/traits/issue-96664.rs

+16
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
// check-pass
2+
3+
#![feature(trait_alias)]
4+
5+
pub trait State = Clone + Send + Sync + PartialOrd + PartialEq + std::fmt::Display;
6+
pub trait RandState<S: State> = FnMut() -> S + Send;
7+
8+
pub trait Evaluator {
9+
type State;
10+
}
11+
12+
pub struct Evolver<E: Evaluator> {
13+
rand_state: Box<dyn RandState<E::State>>,
14+
}
15+
16+
fn main() {}

src/test/ui/traits/issue-96665.rs

+16
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
// check-pass
2+
3+
pub trait Sequence<Item, Subsequence: Sequence<Item, Subsequence>> {}
4+
5+
pub trait NodeWalk<Graph: GraphBase, NodeSubwalk: NodeWalk<Graph, NodeSubwalk>>:
6+
Sequence<Graph::NodeIndex, NodeSubwalk>
7+
{
8+
}
9+
10+
pub trait GraphBase {
11+
type NodeIndex;
12+
}
13+
14+
pub trait WalkableGraph: GraphBase {}
15+
16+
fn main() {}

0 commit comments

Comments
 (0)