Skip to content

Commit 3caca93

Browse files
committed
Auto merge of rust-lang#122501 - compiler-errors:more-wf, r=<try>
Recurse into args in WF even if they have escaping bound vars Might have some subtle breakage but it's afaict always more correct to do this. r? `@ghost`
2 parents fe61575 + 5fed9f0 commit 3caca93

13 files changed

+137
-181
lines changed

compiler/rustc_trait_selection/src/traits/wf.rs

+23-78
Original file line numberDiff line numberDiff line change
@@ -164,7 +164,7 @@ pub fn clause_obligations<'tcx>(
164164
wf.compute(ty.into());
165165
}
166166
ty::ClauseKind::Projection(t) => {
167-
wf.compute_projection(t.projection_ty);
167+
wf.compute_alias(t.projection_ty);
168168
wf.compute(match t.term.unpack() {
169169
ty::TermKind::Ty(ty) => ty.into(),
170170
ty::TermKind::Const(c) => c.into(),
@@ -396,36 +396,17 @@ impl<'a, 'tcx> WfPredicates<'a, 'tcx> {
396396
self.out.extend(obligations);
397397
}
398398

399-
self.out.extend(
400-
trait_ref
401-
.args
402-
.iter()
403-
.enumerate()
404-
.filter(|(_, arg)| {
405-
matches!(arg.unpack(), GenericArgKind::Type(..) | GenericArgKind::Const(..))
406-
})
407-
.filter(|(_, arg)| !arg.has_escaping_bound_vars())
408-
.map(|(i, arg)| {
409-
let mut cause = traits::ObligationCause::misc(self.span, self.body_id);
410-
// The first arg is the self ty - use the correct span for it.
411-
if i == 0 {
412-
if let Some(hir::ItemKind::Impl(hir::Impl { self_ty, .. })) =
413-
item.map(|i| &i.kind)
414-
{
415-
cause.span = self_ty.span;
416-
}
417-
}
418-
traits::Obligation::with_depth(
419-
tcx,
420-
cause,
421-
depth,
422-
param_env,
423-
ty::Binder::dummy(ty::PredicateKind::Clause(ty::ClauseKind::WellFormed(
424-
arg,
425-
))),
426-
)
427-
}),
428-
);
399+
if let Some(hir::ItemKind::Impl(hir::Impl { self_ty, .. })) = item.map(|i| &i.kind) {
400+
// FIXME: Could generalize this hack.
401+
let span = std::mem::replace(&mut self.span, self_ty.span);
402+
// make sure that the trait ref is WF.
403+
trait_ref.args[0].visit_with(self);
404+
self.span = span;
405+
(&trait_ref.args[1..]).visit_with(self);
406+
} else {
407+
// make sure that the trait ref is WF.
408+
trait_ref.visit_with(self);
409+
}
429410
}
430411

431412
// Compute the obligations that are required for `trait_ref` to be WF,
@@ -436,9 +417,9 @@ impl<'a, 'tcx> WfPredicates<'a, 'tcx> {
436417
}
437418
}
438419

439-
/// Pushes the obligations required for `trait_ref::Item` to be WF
420+
/// Pushes the obligations required for an alias (except inherent) to be WF
440421
/// into `self.out`.
441-
fn compute_projection(&mut self, data: ty::AliasTy<'tcx>) {
422+
fn compute_alias(&mut self, data: ty::AliasTy<'tcx>) {
442423
// A projection is well-formed if
443424
//
444425
// (a) its predicates hold (*)
@@ -463,9 +444,13 @@ impl<'a, 'tcx> WfPredicates<'a, 'tcx> {
463444
let obligations = self.nominal_obligations(data.def_id, data.args);
464445
self.out.extend(obligations);
465446

466-
self.compute_projection_args(data.args);
447+
// Make sure that projection args are WF.
448+
data.visit_with(self);
467449
}
468450

451+
/// Pushes the obligations required for an inherent alias to be WF
452+
/// into `self.out`.
453+
// FIXME(inherent_associated_types): Merge this function with `fn compute_alias`.
469454
fn compute_inherent_projection(&mut self, data: ty::AliasTy<'tcx>) {
470455
// An inherent projection is well-formed if
471456
//
@@ -490,33 +475,8 @@ impl<'a, 'tcx> WfPredicates<'a, 'tcx> {
490475
self.out.extend(obligations);
491476
}
492477

493-
self.compute_projection_args(data.args);
494-
}
495-
496-
fn compute_projection_args(&mut self, args: GenericArgsRef<'tcx>) {
497-
let tcx = self.tcx();
498-
let cause = self.cause(traits::WellFormed(None));
499-
let param_env = self.param_env;
500-
let depth = self.recursion_depth;
501-
502-
self.out.extend(
503-
args.iter()
504-
.filter(|arg| {
505-
matches!(arg.unpack(), GenericArgKind::Type(..) | GenericArgKind::Const(..))
506-
})
507-
.filter(|arg| !arg.has_escaping_bound_vars())
508-
.map(|arg| {
509-
traits::Obligation::with_depth(
510-
tcx,
511-
cause.clone(),
512-
depth,
513-
param_env,
514-
ty::Binder::dummy(ty::PredicateKind::Clause(ty::ClauseKind::WellFormed(
515-
arg,
516-
))),
517-
)
518-
}),
519-
);
478+
// Make sure that projection args are WF.
479+
data.visit_with(self);
520480
}
521481

522482
fn require_sized(&mut self, subty: Ty<'tcx>, cause: traits::ObligationCauseCode<'tcx>) {
@@ -688,8 +648,8 @@ impl<'a, 'tcx> TypeVisitor<TyCtxt<'tcx>> for WfPredicates<'a, 'tcx> {
688648
// Simple cases that are WF if their type args are WF.
689649
}
690650

691-
ty::Alias(ty::Projection, data) => {
692-
self.compute_projection(data);
651+
ty::Alias(ty::Projection | ty::Opaque | ty::Weak, data) => {
652+
self.compute_alias(data);
693653
return; // Subtree handled by compute_projection.
694654
}
695655
ty::Alias(ty::Inherent, data) => {
@@ -791,21 +751,6 @@ impl<'a, 'tcx> TypeVisitor<TyCtxt<'tcx>> for WfPredicates<'a, 'tcx> {
791751
// types appearing in the fn signature.
792752
}
793753

794-
ty::Alias(ty::Opaque, ty::AliasTy { def_id, args, .. }) => {
795-
// All of the requirements on type parameters
796-
// have already been checked for `impl Trait` in
797-
// return position. We do need to check type-alias-impl-trait though.
798-
if self.tcx().is_type_alias_impl_trait(def_id) {
799-
let obligations = self.nominal_obligations(def_id, args);
800-
self.out.extend(obligations);
801-
}
802-
}
803-
804-
ty::Alias(ty::Weak, ty::AliasTy { def_id, args, .. }) => {
805-
let obligations = self.nominal_obligations(def_id, args);
806-
self.out.extend(obligations);
807-
}
808-
809754
ty::Dynamic(data, r, _) => {
810755
// WfObject
811756
//

tests/ui/impl-trait/in-trait/return-dont-satisfy-bounds.rs

+1
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ impl Foo<char> for Bar {
99
//~^ ERROR: the trait bound `impl Foo<u8>: Foo<char>` is not satisfied [E0277]
1010
//~| ERROR: the trait bound `Bar: Foo<u8>` is not satisfied [E0277]
1111
//~| ERROR: impl has stricter requirements than trait
12+
//~| ERROR: the trait bound `F2: Foo<u8>` is not satisfied
1213
self
1314
}
1415
}

tests/ui/impl-trait/in-trait/return-dont-satisfy-bounds.stderr

+17-1
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,22 @@ note: required by a bound in `Foo::{synthetic#0}`
1111
LL | fn foo<F2>(self) -> impl Foo<T>;
1212
| ^^^^^^ required by this bound in `Foo::{synthetic#0}`
1313

14+
error[E0277]: the trait bound `F2: Foo<u8>` is not satisfied
15+
--> $DIR/return-dont-satisfy-bounds.rs:8:34
16+
|
17+
LL | fn foo<F2: Foo<u8>>(self) -> impl Foo<u8> {
18+
| ^^^^^^^^^^^^ the trait `Foo<u8>` is not implemented for `F2`
19+
|
20+
note: required by a bound in `<Bar as Foo<char>>::foo`
21+
--> $DIR/return-dont-satisfy-bounds.rs:8:16
22+
|
23+
LL | fn foo<F2: Foo<u8>>(self) -> impl Foo<u8> {
24+
| ^^^^^^^ required by this bound in `<Bar as Foo<char>>::foo`
25+
help: consider further restricting this bound
26+
|
27+
LL | fn foo<F2: Foo<u8> + Foo<u8>>(self) -> impl Foo<u8> {
28+
| +++++++++
29+
1430
error[E0276]: impl has stricter requirements than trait
1531
--> $DIR/return-dont-satisfy-bounds.rs:8:16
1632
|
@@ -32,7 +48,7 @@ LL | self
3248
= help: the trait `Foo<char>` is implemented for `Bar`
3349
= help: for that trait implementation, expected `char`, found `u8`
3450

35-
error: aborting due to 3 previous errors
51+
error: aborting due to 4 previous errors
3652

3753
Some errors have detailed explanations: E0276, E0277.
3854
For more information about an error, try `rustc --explain E0276`.

tests/ui/implied-bounds/from-trait-impl.stderr

+5-5
Original file line numberDiff line numberDiff line change
@@ -7,13 +7,13 @@ LL | fn func1(foo: Foo<(&str,)>) {
77
= note: type must satisfy the static lifetime
88

99
error[E0310]: the parameter type `X` may not live long enough
10-
--> $DIR/from-trait-impl.rs:20:23
10+
--> $DIR/from-trait-impl.rs:20:9
1111
|
1212
LL | impl<X> TestTrait for [Foo<(X,)>; 1] {}
13-
| ^^^^^^^^^^^^^^
14-
| |
15-
| the parameter type `X` must be valid for the static lifetime...
16-
| ...so that the type `X` will meet its required lifetime bounds
13+
| ^^^^^^^^^
14+
| |
15+
| the parameter type `X` must be valid for the static lifetime...
16+
| ...so that the type `X` will meet its required lifetime bounds
1717
|
1818
help: consider adding an explicit lifetime bound
1919
|

tests/ui/inference/issue-80409.no-compat.stderr

-14
This file was deleted.

tests/ui/inference/issue-80409.rs

+1-16
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,3 @@
1-
// This should not pass, because `usize: Fsm` does not hold. However, it currently ICEs.
2-
3-
// ignore-tidy-linelength
4-
5-
//@ revisions: compat no-compat
6-
//@[compat] check-pass
7-
//@[no-compat] compile-flags: -Zno-implied-bounds-compat
8-
//@[no-compat] check-fail
9-
//@[no-compat] known-bug: #80409
10-
//@[no-compat] failure-status: 101
11-
//@[no-compat] normalize-stderr-test "delayed at.*" -> ""
12-
//@[no-compat] normalize-stderr-test "note: .*\n\n" -> ""
13-
//@[no-compat] normalize-stderr-test "thread 'rustc' panicked.*\n" -> ""
14-
//@[no-compat] normalize-stderr-test "(error: internal compiler error: [^:]+):\d+:\d+: " -> "$1:LL:CC: "
15-
//@[no-compat] rustc-env:RUST_BACKTRACE=0
16-
171
#![allow(unreachable_code, unused)]
182

193
use std::marker::PhantomData;
@@ -34,6 +18,7 @@ struct FsmStateBuilder<TFsm> {
3418

3519
impl<TFsm> FsmStateBuilder<TFsm> {
3620
fn on_entry<TAction: Fn(&mut StateContext<'_, TFsm>)>(&self, _action: TAction) {}
21+
//~^ ERROR the trait bound `TFsm: Fsm` is not satisfied
3722
}
3823

3924
trait Fsm {

tests/ui/lifetimes/issue-76168-hr-outlives-3.rs

+1
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ async fn wrapper<F>(f: F)
77
//~^ ERROR: expected a `FnOnce(&'a mut i32)` closure, found `i32`
88
//~| ERROR: expected a `FnOnce(&'a mut i32)` closure, found `i32`
99
//~| ERROR: expected a `FnOnce(&'a mut i32)` closure, found `i32`
10+
//~| ERROR: expected a `FnOnce(&'a mut i32)` closure, found `i32`
1011
where
1112
F:,
1213
for<'a> <i32 as FnOnce<(&'a mut i32,)>>::Output: Future<Output = ()> + 'a,

tests/ui/lifetimes/issue-76168-hr-outlives-3.stderr

+19-4
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ LL | / async fn wrapper<F>(f: F)
55
LL | |
66
LL | |
77
LL | |
8-
LL | | where
8+
... |
99
LL | | F:,
1010
LL | | for<'a> <i32 as FnOnce<(&'a mut i32,)>>::Output: Future<Output = ()> + 'a,
1111
| |__________________________________________________________________________^ expected an `FnOnce(&'a mut i32)` closure, found `i32`
@@ -27,15 +27,30 @@ LL | / async fn wrapper<F>(f: F)
2727
LL | |
2828
LL | |
2929
LL | |
30-
LL | | where
30+
... |
3131
LL | | F:,
3232
LL | | for<'a> <i32 as FnOnce<(&'a mut i32,)>>::Output: Future<Output = ()> + 'a,
3333
| |__________________________________________________________________________^ expected an `FnOnce(&'a mut i32)` closure, found `i32`
3434
|
3535
= help: the trait `for<'a> FnOnce<(&'a mut i32,)>` is not implemented for `i32`
3636

3737
error[E0277]: expected a `FnOnce(&'a mut i32)` closure, found `i32`
38-
--> $DIR/issue-76168-hr-outlives-3.rs:13:1
38+
--> $DIR/issue-76168-hr-outlives-3.rs:6:1
39+
|
40+
LL | / async fn wrapper<F>(f: F)
41+
LL | |
42+
LL | |
43+
LL | |
44+
... |
45+
LL | | F:,
46+
LL | | for<'a> <i32 as FnOnce<(&'a mut i32,)>>::Output: Future<Output = ()> + 'a,
47+
| |__________________________________________________________________________^ expected an `FnOnce(&'a mut i32)` closure, found `i32`
48+
|
49+
= help: the trait `for<'a> FnOnce<(&'a mut i32,)>` is not implemented for `i32`
50+
= note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
51+
52+
error[E0277]: expected a `FnOnce(&'a mut i32)` closure, found `i32`
53+
--> $DIR/issue-76168-hr-outlives-3.rs:14:1
3954
|
4055
LL | / {
4156
LL | |
@@ -46,6 +61,6 @@ LL | | }
4661
|
4762
= help: the trait `for<'a> FnOnce<(&'a mut i32,)>` is not implemented for `i32`
4863

49-
error: aborting due to 4 previous errors
64+
error: aborting due to 5 previous errors
5065

5166
For more information about this error, try `rustc --explain E0277`.

0 commit comments

Comments
 (0)