Skip to content

Commit 18cae26

Browse files
committed
Auto merge of #88441 - jackh726:closure_norm, r=nikomatsakis
Normalize obligations for closure confirmation Based on #90017 Fixes #74261 Fixes #71955 Fixes #88459 r? `@nikomatsakis`
2 parents d32993a + cacc3ee commit 18cae26

File tree

17 files changed

+263
-87
lines changed

17 files changed

+263
-87
lines changed

compiler/rustc_middle/src/ty/print/pretty.rs

+1
Original file line numberDiff line numberDiff line change
@@ -744,6 +744,7 @@ pub trait PrettyPrinter<'tcx>:
744744
p!(print_def_path(did, substs));
745745
if !substs.as_closure().is_valid() {
746746
p!(" closure_substs=(unavailable)");
747+
p!(write(" substs={:?}", substs));
747748
} else {
748749
p!(" closure_kind_ty=", print(substs.as_closure().kind_ty()));
749750
p!(

compiler/rustc_trait_selection/src/traits/project.rs

+14-2
Original file line numberDiff line numberDiff line change
@@ -1734,7 +1734,7 @@ fn confirm_callable_candidate<'cx, 'tcx>(
17341734
ty: ret_type,
17351735
});
17361736

1737-
confirm_param_env_candidate(selcx, obligation, predicate, false)
1737+
confirm_param_env_candidate(selcx, obligation, predicate, true)
17381738
}
17391739

17401740
fn confirm_param_env_candidate<'cx, 'tcx>(
@@ -1754,8 +1754,18 @@ fn confirm_param_env_candidate<'cx, 'tcx>(
17541754
);
17551755

17561756
let cache_projection = cache_entry.projection_ty;
1757-
let obligation_projection = obligation.predicate;
17581757
let mut nested_obligations = Vec::new();
1758+
let obligation_projection = obligation.predicate;
1759+
let obligation_projection = ensure_sufficient_stack(|| {
1760+
normalize_with_depth_to(
1761+
selcx,
1762+
obligation.param_env,
1763+
obligation.cause.clone(),
1764+
obligation.recursion_depth + 1,
1765+
obligation_projection,
1766+
&mut nested_obligations,
1767+
)
1768+
});
17591769
let cache_projection = if potentially_unnormalized_candidate {
17601770
ensure_sufficient_stack(|| {
17611771
normalize_with_depth_to(
@@ -1771,6 +1781,8 @@ fn confirm_param_env_candidate<'cx, 'tcx>(
17711781
cache_projection
17721782
};
17731783

1784+
debug!(?cache_projection, ?obligation_projection);
1785+
17741786
match infcx.at(cause, param_env).eq(cache_projection, obligation_projection) {
17751787
Ok(InferOk { value: _, obligations }) => {
17761788
nested_obligations.extend(obligations);

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

+24-10
Original file line numberDiff line numberDiff line change
@@ -620,23 +620,37 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
620620
_ => bug!("closure candidate for non-closure {:?}", obligation),
621621
};
622622

623+
let obligation_predicate = obligation.predicate.to_poly_trait_ref();
624+
let Normalized { value: obligation_predicate, mut obligations } =
625+
ensure_sufficient_stack(|| {
626+
normalize_with_depth(
627+
self,
628+
obligation.param_env,
629+
obligation.cause.clone(),
630+
obligation.recursion_depth + 1,
631+
obligation_predicate,
632+
)
633+
});
634+
623635
let trait_ref = self.closure_trait_ref_unnormalized(obligation, substs);
624-
let Normalized { value: trait_ref, mut obligations } = ensure_sufficient_stack(|| {
625-
normalize_with_depth(
626-
self,
627-
obligation.param_env,
628-
obligation.cause.clone(),
629-
obligation.recursion_depth + 1,
630-
trait_ref,
631-
)
632-
});
636+
let Normalized { value: trait_ref, obligations: trait_ref_obligations } =
637+
ensure_sufficient_stack(|| {
638+
normalize_with_depth(
639+
self,
640+
obligation.param_env,
641+
obligation.cause.clone(),
642+
obligation.recursion_depth + 1,
643+
trait_ref,
644+
)
645+
});
633646

634647
debug!(?closure_def_id, ?trait_ref, ?obligations, "confirm closure candidate obligations");
635648

649+
obligations.extend(trait_ref_obligations);
636650
obligations.extend(self.confirm_poly_trait_refs(
637651
obligation.cause.clone(),
638652
obligation.param_env,
639-
obligation.predicate.to_poly_trait_ref(),
653+
obligation_predicate,
640654
trait_ref,
641655
)?);
642656

src/test/ui/closures/print/closure-print-generic-trim-off-verbose-2.stderr

+1-1
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ LL | let c1 : () = c;
99
| expected due to this
1010
|
1111
= note: expected unit type `()`
12-
found closure `[mod1::f<T>::{closure#0} closure_substs=(unavailable)]`
12+
found closure `[mod1::f<T>::{closure#0} closure_substs=(unavailable) substs=[T, _#25t, extern "rust-call" fn(()), _#26t]]`
1313
help: use parentheses to call this closure
1414
|
1515
LL | let c1 : () = c();

src/test/ui/closures/print/closure-print-generic-verbose-2.stderr

+1-1
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ LL | let c1 : () = c;
99
| expected due to this
1010
|
1111
= note: expected unit type `()`
12-
found closure `[f<T>::{closure#0} closure_substs=(unavailable)]`
12+
found closure `[f<T>::{closure#0} closure_substs=(unavailable) substs=[T, _#25t, extern "rust-call" fn(()), _#26t]]`
1313
help: use parentheses to call this closure
1414
|
1515
LL | let c1 : () = c();

src/test/ui/closures/print/closure-print-verbose.stderr

+1-1
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ LL | let foo: fn(u8) -> u8 = |v: u8| { a += v; a };
77
| expected due to this
88
|
99
= note: expected fn pointer `fn(u8) -> u8`
10-
found closure `[main::{closure#0} closure_substs=(unavailable)]`
10+
found closure `[main::{closure#0} closure_substs=(unavailable) substs=[i8, extern "rust-call" fn((u8,)) -> u8, _#6t]]`
1111
note: closures can only be coerced to `fn` types if they do not capture any variables
1212
--> $DIR/closure-print-verbose.rs:10:39
1313
|
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
// check-pass
2+
3+
#![feature(generic_associated_types)]
4+
5+
trait Trait {
6+
type Assoc<'a>;
7+
}
8+
9+
fn f<T: Trait>(_: T, _: impl Fn(T::Assoc<'_>)) {}
10+
11+
struct Type;
12+
13+
impl Trait for Type {
14+
type Assoc<'a> = ();
15+
}
16+
17+
fn main() {
18+
f(Type, |_|());
19+
}

src/test/ui/issues/issue-44005.rs src/test/ui/higher-rank-trait-bounds/normalize-under-binder/issue-44005.rs

+2-1
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
// check-pass
2+
13
pub trait Foo<'a> {
24
type Bar;
35
fn foo(&'a self) -> Self::Bar;
@@ -24,7 +26,6 @@ pub fn catalyst(x: &i32) {
2426

2527
pub fn broken<F: Fn(&i32)>(x: &i32, f: F) {
2628
uncallable(x, |y| f(y));
27-
//~^ type mismatch
2829
}
2930

3031
fn main() {}

src/test/ui/higher-rank-trait-bounds/normalize-under-binder/issue-62529-1.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -77,7 +77,7 @@ where P: Execute + 'static {
7777
}
7878

7979
fn main() {
80-
task(annotate( //~ type mismatch
80+
task(annotate(
8181
//~^ the size
8282
//~^^ the trait bound
8383
Annotate::<RefMutFamily<usize>>::new(),

src/test/ui/higher-rank-trait-bounds/normalize-under-binder/issue-62529-1.stderr

+2-29
Original file line numberDiff line numberDiff line change
@@ -1,29 +1,3 @@
1-
error[E0631]: type mismatch in closure arguments
2-
--> $DIR/issue-62529-1.rs:80:10
3-
|
4-
LL | task(annotate(
5-
| _____----_^
6-
| | |
7-
| | required by a bound introduced by this call
8-
LL | |
9-
LL | |
10-
LL | | Annotate::<RefMutFamily<usize>>::new(),
11-
LL | | |value: &mut usize| {
12-
| | ------------------- found signature of `for<'r> fn(&'r mut usize) -> _`
13-
LL | | *value = 2;
14-
LL | | }
15-
LL | | ));
16-
| |_____^ expected signature of `for<'r> fn(<RefMutFamily<usize> as FamilyLt<'r>>::Out) -> _`
17-
|
18-
note: required by a bound in `annotate`
19-
--> $DIR/issue-62529-1.rs:44:8
20-
|
21-
LL | fn annotate<F, Q>(_q: Annotate<Q>, func: F) -> impl Execute + 'static
22-
| -------- required by a bound in this
23-
LL | where
24-
LL | F: for<'r> FnOnce(<<Q as Inject>::I as FamilyLt<'r>>::Out) + 'static,
25-
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `annotate`
26-
271
error[E0277]: the size for values of type `impl Execute` cannot be known at compilation time
282
--> $DIR/issue-62529-1.rs:80:10
293
|
@@ -73,7 +47,6 @@ LL | fn task<P>(processor: P) -> Task
7347
LL | where P: Execute + 'static {
7448
| ^^^^^^^ required by this bound in `task`
7549

76-
error: aborting due to 3 previous errors
50+
error: aborting due to 2 previous errors
7751

78-
Some errors have detailed explanations: E0277, E0631.
79-
For more information about an error, try `rustc --explain E0277`.
52+
For more information about this error, try `rustc --explain E0277`.

src/test/ui/higher-rank-trait-bounds/normalize-under-binder/issue-70120.rs

+3-1
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
// check-pass
2+
13
pub trait MyTrait<'a> {
24
type Output: 'a;
35
fn gimme_value(&self) -> Self::Output;
@@ -23,7 +25,7 @@ where
2325

2426
fn main() {
2527
let struc = MyStruct;
26-
meow(struc, |foo| { //~ type mismatch
28+
meow(struc, |foo| {
2729
println!("{:?}", foo);
2830
})
2931
}

src/test/ui/higher-rank-trait-bounds/normalize-under-binder/issue-70120.stderr

-20
This file was deleted.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,92 @@
1+
error: implementation of `Parser` is not general enough
2+
--> $DIR/issue-71955.rs:52:5
3+
|
4+
LL | foo(bar, "string", |s| s.len() == 5);
5+
| ^^^ implementation of `Parser` is not general enough
6+
|
7+
= note: `for<'a> fn(&'a str) -> (&'a str, &'a str) {bar}` must implement `Parser<'0>`, for any lifetime `'0`...
8+
= note: ...but it actually implements `Parser<'1>`, for some specific lifetime `'1`
9+
10+
error: implementation of `Parser` is not general enough
11+
--> $DIR/issue-71955.rs:52:5
12+
|
13+
LL | foo(bar, "string", |s| s.len() == 5);
14+
| ^^^ implementation of `Parser` is not general enough
15+
|
16+
= note: `for<'a> fn(&'a str) -> (&'a str, &'a str) {bar}` must implement `Parser<'0>`, for any lifetime `'0`...
17+
= note: ...but it actually implements `Parser<'1>`, for some specific lifetime `'1`
18+
19+
error: implementation of `Parser` is not general enough
20+
--> $DIR/issue-71955.rs:52:5
21+
|
22+
LL | foo(bar, "string", |s| s.len() == 5);
23+
| ^^^ implementation of `Parser` is not general enough
24+
|
25+
= note: `for<'a> fn(&'a str) -> (&'a str, &'a str) {bar}` must implement `Parser<'0>`, for any lifetime `'0`...
26+
= note: ...but it actually implements `Parser<'1>`, for some specific lifetime `'1`
27+
28+
error: implementation of `Parser` is not general enough
29+
--> $DIR/issue-71955.rs:52:5
30+
|
31+
LL | foo(bar, "string", |s| s.len() == 5);
32+
| ^^^ implementation of `Parser` is not general enough
33+
|
34+
= note: `for<'a> fn(&'a str) -> (&'a str, &'a str) {bar}` must implement `Parser<'0>`, for any lifetime `'0`...
35+
= note: ...but it actually implements `Parser<'1>`, for some specific lifetime `'1`
36+
37+
error: implementation of `Parser` is not general enough
38+
--> $DIR/issue-71955.rs:52:5
39+
|
40+
LL | foo(bar, "string", |s| s.len() == 5);
41+
| ^^^ implementation of `Parser` is not general enough
42+
|
43+
= note: `for<'a> fn(&'a str) -> (&'a str, &'a str) {bar}` must implement `Parser<'0>`, for any lifetime `'0`...
44+
= note: ...but it actually implements `Parser<'1>`, for some specific lifetime `'1`
45+
46+
error: implementation of `Parser` is not general enough
47+
--> $DIR/issue-71955.rs:58:5
48+
|
49+
LL | foo(baz, "string", |s| s.0.len() == 5);
50+
| ^^^ implementation of `Parser` is not general enough
51+
|
52+
= note: `for<'a> fn(&'a str) -> (&'a str, Wrapper<'a>) {baz}` must implement `Parser<'0>`, for any lifetime `'0`...
53+
= note: ...but it actually implements `Parser<'1>`, for some specific lifetime `'1`
54+
55+
error: implementation of `Parser` is not general enough
56+
--> $DIR/issue-71955.rs:58:5
57+
|
58+
LL | foo(baz, "string", |s| s.0.len() == 5);
59+
| ^^^ implementation of `Parser` is not general enough
60+
|
61+
= note: `for<'a> fn(&'a str) -> (&'a str, Wrapper<'a>) {baz}` must implement `Parser<'0>`, for any lifetime `'0`...
62+
= note: ...but it actually implements `Parser<'1>`, for some specific lifetime `'1`
63+
64+
error: implementation of `Parser` is not general enough
65+
--> $DIR/issue-71955.rs:58:5
66+
|
67+
LL | foo(baz, "string", |s| s.0.len() == 5);
68+
| ^^^ implementation of `Parser` is not general enough
69+
|
70+
= note: `for<'a> fn(&'a str) -> (&'a str, Wrapper<'a>) {baz}` must implement `Parser<'0>`, for any lifetime `'0`...
71+
= note: ...but it actually implements `Parser<'1>`, for some specific lifetime `'1`
72+
73+
error: implementation of `Parser` is not general enough
74+
--> $DIR/issue-71955.rs:58:5
75+
|
76+
LL | foo(baz, "string", |s| s.0.len() == 5);
77+
| ^^^ implementation of `Parser` is not general enough
78+
|
79+
= note: `for<'a> fn(&'a str) -> (&'a str, Wrapper<'a>) {baz}` must implement `Parser<'0>`, for any lifetime `'0`...
80+
= note: ...but it actually implements `Parser<'1>`, for some specific lifetime `'1`
81+
82+
error: implementation of `Parser` is not general enough
83+
--> $DIR/issue-71955.rs:58:5
84+
|
85+
LL | foo(baz, "string", |s| s.0.len() == 5);
86+
| ^^^ implementation of `Parser` is not general enough
87+
|
88+
= note: `for<'a> fn(&'a str) -> (&'a str, Wrapper<'a>) {baz}` must implement `Parser<'0>`, for any lifetime `'0`...
89+
= note: ...but it actually implements `Parser<'1>`, for some specific lifetime `'1`
90+
91+
error: aborting due to 10 previous errors
92+
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
error: fatal error triggered by #[rustc_error]
2+
--> $DIR/issue-71955.rs:42:1
3+
|
4+
LL | fn main() {
5+
| ^^^^^^^^^
6+
7+
error: aborting due to previous error
8+

0 commit comments

Comments
 (0)