Skip to content

Commit 31b66a5

Browse files
Fix new solver, require supertrait projections are WF for back-compat
1 parent 74ece08 commit 31b66a5

File tree

8 files changed

+79
-24
lines changed

8 files changed

+79
-24
lines changed

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

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
44
use derive_where::derive_where;
55
use rustc_ast_ir::{Movability, Mutability};
6-
use rustc_type_ir::data_structures::HashMap;
6+
use rustc_type_ir::data_structures::{HashMap, HashSet};
77
use rustc_type_ir::fold::{TypeFoldable, TypeFolder, TypeSuperFoldable};
88
use rustc_type_ir::inherent::*;
99
use rustc_type_ir::lang_items::TraitSolverLangItem;
@@ -841,6 +841,9 @@ where
841841
.map(|(pred, _)| pred),
842842
));
843843

844+
let specified_associated_projections: HashSet<_> =
845+
object_bounds.projection_bounds().into_iter().map(|proj| proj.item_def_id()).collect();
846+
844847
// FIXME(associated_const_equality): Also add associated consts to
845848
// the requirements here.
846849
for associated_type_def_id in cx.associated_type_def_ids(trait_ref.def_id) {
@@ -850,6 +853,11 @@ where
850853
continue;
851854
}
852855

856+
// We don't require these bounds to hold for supertrait implied projection bounds.
857+
if !specified_associated_projections.contains(&associated_type_def_id) {
858+
continue;
859+
}
860+
853861
requirements
854862
.extend(cx.item_bounds(associated_type_def_id).iter_instantiated(cx, trait_ref.args));
855863
}

compiler/rustc_trait_selection/src/traits/wf.rs

Lines changed: 35 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
use std::iter;
22

3+
use rustc_data_structures::fx::FxHashSet;
34
use rustc_hir as hir;
45
use rustc_hir::lang_items::LangItem;
56
use rustc_infer::traits::{ObligationCauseCode, PredicateObligations};
@@ -10,6 +11,7 @@ use rustc_middle::ty::{
1011
};
1112
use rustc_span::def_id::{CRATE_DEF_ID, DefId, LocalDefId};
1213
use rustc_span::{DUMMY_SP, Span};
14+
use rustc_type_ir::{Upcast, elaborate};
1315
use tracing::{debug, instrument, trace};
1416

1517
use crate::infer::InferCtxt;
@@ -632,7 +634,6 @@ impl<'a, 'tcx> WfPredicates<'a, 'tcx> {
632634
// am looking forward to the future here.
633635
if !data.has_escaping_bound_vars() && !region.has_escaping_bound_vars() {
634636
let implicit_bounds = object_region_bounds(self.tcx(), data);
635-
636637
let explicit_bound = region;
637638

638639
self.out.reserve(implicit_bounds.len());
@@ -853,6 +854,39 @@ impl<'a, 'tcx> TypeVisitor<TyCtxt<'tcx>> for WfPredicates<'a, 'tcx> {
853854
));
854855
}
855856
}
857+
858+
// Finally, for backwards compatibility reasons, we imply the outlives bounds
859+
// that come from supertrait projections since we used to elaborate them into
860+
// the dyn trait itself.
861+
//
862+
// See <https://github.com/rust-lang/rust/pull/133397> when this was changed.
863+
let shadowed_projections: FxHashSet<_> =
864+
data.projection_bounds().map(|proj| proj.item_def_id()).collect();
865+
if let Some(principal) = data.principal() {
866+
let principal: ty::Clause<'tcx> = principal
867+
.with_self_ty(self.tcx(), self.tcx().types.trait_object_dummy_self)
868+
.upcast(self.tcx());
869+
for clause in elaborate::elaborate(self.tcx(), [principal]) {
870+
if let Some(proj) = clause.as_projection_clause()
871+
&& !shadowed_projections.contains(&proj.projection_def_id())
872+
{
873+
// A `Self` within the original bound will be instantiated with a
874+
// `trait_object_dummy_self`, so check for that.
875+
let references_self = match proj.skip_binder().term.unpack() {
876+
ty::TermKind::Ty(ty) => ty.walk().any(|arg| {
877+
arg == self.tcx().types.trait_object_dummy_self.into()
878+
}),
879+
// FIXME(associated_const_equality): We should walk the const instead of not doing anything
880+
ty::TermKind::Const(_) => false,
881+
};
882+
if !references_self {
883+
proj.map_bound(|proj| &proj.projection_term.args[1..])
884+
.visit_with(self);
885+
proj.term().visit_with(self);
886+
}
887+
}
888+
}
889+
}
856890
}
857891

858892
// Inference variables are the complicated case, since we don't

src/tools/tidy/src/ui_tests.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ use ignore::Walk;
1717
const ENTRY_LIMIT: u32 = 901;
1818
// FIXME: The following limits should be reduced eventually.
1919

20-
const ISSUES_ENTRY_LIMIT: u32 = 1672;
20+
const ISSUES_ENTRY_LIMIT: u32 = 1673;
2121

2222
const EXPECTED_TEST_FILE_EXTENSIONS: &[&str] = &[
2323
"rs", // test source files

tests/ui/associated-types/issue-59324.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,5 +22,6 @@ pub trait ThriftService<Bug: NotFoo>:
2222

2323
fn with_factory<H>(factory: dyn ThriftService<()>) {}
2424
//~^ ERROR cannot be known at compilation time
25+
//~| ERROR the trait bound `(): Foo` is not satisfied
2526

2627
fn main() {}

tests/ui/associated-types/issue-59324.stderr

Lines changed: 3 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -66,25 +66,13 @@ help: consider further restricting this bound
6666
LL | pub trait ThriftService<Bug: NotFoo + Foo>:
6767
| +++++
6868

69-
error[E0277]: the trait bound `(): Foo` is not satisfied
70-
--> $DIR/issue-59324.rs:23:52
71-
|
72-
LL | fn with_factory<H>(factory: dyn ThriftService<()>) {}
73-
| ^^ the trait `Foo` is not implemented for `()`
74-
|
75-
help: this trait has no implementations, consider adding one
76-
--> $DIR/issue-59324.rs:3:1
77-
|
78-
LL | pub trait Foo: NotFoo {
79-
| ^^^^^^^^^^^^^^^^^^^^^
80-
81-
error[E0277]: the size for values of type `(dyn ThriftService<(), AssocType = _> + 'static)` cannot be known at compilation time
69+
error[E0277]: the size for values of type `(dyn ThriftService<()> + 'static)` cannot be known at compilation time
8270
--> $DIR/issue-59324.rs:23:29
8371
|
8472
LL | fn with_factory<H>(factory: dyn ThriftService<()>) {}
8573
| ^^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time
8674
|
87-
= help: the trait `Sized` is not implemented for `(dyn ThriftService<(), AssocType = _> + 'static)`
75+
= help: the trait `Sized` is not implemented for `(dyn ThriftService<()> + 'static)`
8876
= help: unsized fn params are gated as an unstable feature
8977
help: you can use `impl Trait` as the argument type
9078
|
@@ -95,6 +83,6 @@ help: function arguments must have a statically known size, borrowed types alway
9583
LL | fn with_factory<H>(factory: &dyn ThriftService<()>) {}
9684
| +
9785

98-
error: aborting due to 7 previous errors
86+
error: aborting due to 6 previous errors
9987

10088
For more information about this error, try `rustc --explain E0277`.
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
//@ check-pass
2+
3+
// Make sure that we still deduce outlives bounds from supertrait projections
4+
// and require them for well-formedness.
5+
6+
trait Trait {
7+
type Assoc;
8+
}
9+
10+
trait Bar {
11+
type Assoc;
12+
}
13+
14+
trait Foo<'a, T: 'a>: Bar<Assoc = &'a T> {
15+
16+
}
17+
18+
fn outlives<'a, T: 'a>() {}
19+
20+
fn implied_outlives<'a, T: Trait>(x: &dyn Foo<'a, T::Assoc>) {
21+
outlives::<'a, T::Assoc>();
22+
}
23+
24+
fn main() {}

tests/ui/wf/hir-wf-canonicalized.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,8 +9,8 @@ trait Callback<T: Foo>: Fn(&Bar<'_, T>, &T::V) {}
99
struct Bar<'a, T> {
1010
callback: Box<dyn Callback<dyn Callback<Bar<'a, T>>>>,
1111
//~^ ERROR the trait bound `Bar<'a, T>: Foo` is not satisfied
12-
//~| ERROR the trait bound `(dyn Callback<Bar<'a, T>, Output = ()> + 'static): Foo` is not satisfied
13-
//~| ERROR the size for values of type `(dyn Callback<Bar<'a, T>, Output = ()> + 'static)` cannot be known at compilation time
12+
//~| ERROR the trait bound `(dyn Callback<Bar<'a, T>> + 'static): Foo` is not satisfied
13+
//~| ERROR the size for values of type `(dyn Callback<Bar<'a, T>> + 'static)` cannot be known at compilation time
1414
}
1515

1616
impl<T: Foo> Bar<'_, Bar<'_, T>> {}

tests/ui/wf/hir-wf-canonicalized.stderr

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -10,25 +10,25 @@ help: this trait has no implementations, consider adding one
1010
LL | trait Foo {
1111
| ^^^^^^^^^
1212

13-
error[E0277]: the trait bound `(dyn Callback<Bar<'a, T>, Output = ()> + 'static): Foo` is not satisfied
13+
error[E0277]: the trait bound `(dyn Callback<Bar<'a, T>> + 'static): Foo` is not satisfied
1414
--> $DIR/hir-wf-canonicalized.rs:10:15
1515
|
1616
LL | callback: Box<dyn Callback<dyn Callback<Bar<'a, T>>>>,
17-
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `Foo` is not implemented for `(dyn Callback<Bar<'a, T>, Output = ()> + 'static)`
17+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `Foo` is not implemented for `(dyn Callback<Bar<'a, T>> + 'static)`
1818
|
1919
help: this trait has no implementations, consider adding one
2020
--> $DIR/hir-wf-canonicalized.rs:3:1
2121
|
2222
LL | trait Foo {
2323
| ^^^^^^^^^
2424

25-
error[E0277]: the size for values of type `(dyn Callback<Bar<'a, T>, Output = ()> + 'static)` cannot be known at compilation time
25+
error[E0277]: the size for values of type `(dyn Callback<Bar<'a, T>> + 'static)` cannot be known at compilation time
2626
--> $DIR/hir-wf-canonicalized.rs:10:15
2727
|
2828
LL | callback: Box<dyn Callback<dyn Callback<Bar<'a, T>>>>,
2929
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time
3030
|
31-
= help: the trait `Sized` is not implemented for `(dyn Callback<Bar<'a, T>, Output = ()> + 'static)`
31+
= help: the trait `Sized` is not implemented for `(dyn Callback<Bar<'a, T>> + 'static)`
3232
note: required by an implicit `Sized` bound in `Bar`
3333
--> $DIR/hir-wf-canonicalized.rs:9:16
3434
|

0 commit comments

Comments
 (0)