Skip to content

Commit 12d7202

Browse files
authored
Rollup merge of #149320 - ShoyuVanilla:normalized-fudge, r=lcnr
-Znext-solver: normalize expected function input types when fudging Fixes rust-lang/trait-system-refactor-initiative#252 r? lcnr
2 parents 725d8bd + 9f584ff commit 12d7202

16 files changed

+499
-13
lines changed

compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -243,6 +243,11 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
243243
let expected_input_tys: Option<Vec<_>> = expectation
244244
.only_has_type(self)
245245
.and_then(|expected_output| {
246+
// FIXME(#149379): This operation results in expected input
247+
// types which are potentially not well-formed or for whom the
248+
// function where-bounds don't actually hold. This results
249+
// in weird bugs when later treating these expectations as if
250+
// they were actually correct.
246251
self.fudge_inference_if_ok(|| {
247252
let ocx = ObligationCtxt::new(self);
248253

@@ -252,6 +257,39 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
252257
// No argument expectations are produced if unification fails.
253258
let origin = self.misc(call_span);
254259
ocx.sup(&origin, self.param_env, expected_output, formal_output)?;
260+
261+
let formal_input_tys_ns;
262+
let formal_input_tys = if self.next_trait_solver() {
263+
// In the new solver, the normalizations are done lazily.
264+
// Because of this, if we encounter unnormalized alias types inside this
265+
// fudge scope, we might lose the relationships between them and other vars
266+
// when fudging inference variables created here.
267+
// So, we utilize generalization to normalize aliases by adding a new
268+
// inference var and equating it with the type we want to pull out of the
269+
// fudge scope.
270+
formal_input_tys_ns = formal_input_tys
271+
.iter()
272+
.map(|&ty| {
273+
// If we replace a (unresolved) inference var with a new inference
274+
// var, it will be eventually resolved to itself and this will
275+
// weaken type inferences as the new inference var will be fudged
276+
// out and lose all relationships with other vars while the former
277+
// will not be fudged.
278+
if ty.is_ty_var() {
279+
return ty;
280+
}
281+
282+
let generalized_ty = self.next_ty_var(call_span);
283+
ocx.eq(&origin, self.param_env, ty, generalized_ty).unwrap();
284+
generalized_ty
285+
})
286+
.collect_vec();
287+
288+
formal_input_tys_ns.as_slice()
289+
} else {
290+
formal_input_tys
291+
};
292+
255293
if !ocx.try_evaluate_obligations().is_empty() {
256294
return Err(TypeError::Mismatch);
257295
}
Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
error[E0308]: mismatched types
2+
--> $DIR/fn-ret-trait-object-propagated-to-inputs-issue-149379-1.rs:16:33
3+
|
4+
LL | let _: Box<dyn Send> = foo(((), ()));
5+
| ^^ expected trait object, found `()`
6+
|
7+
= note: expected trait object `dyn Send`
8+
found unit type `()`
9+
10+
error[E0277]: the size for values of type `dyn Send` cannot be known at compilation time
11+
--> $DIR/fn-ret-trait-object-propagated-to-inputs-issue-149379-1.rs:16:32
12+
|
13+
LL | let _: Box<dyn Send> = foo(((), ()));
14+
| --- ^^^^^^^^ doesn't have a size known at compile-time
15+
| |
16+
| required by a bound introduced by this call
17+
|
18+
= help: the trait `Sized` is not implemented for `dyn Send`
19+
note: required by an implicit `Sized` bound in `foo`
20+
--> $DIR/fn-ret-trait-object-propagated-to-inputs-issue-149379-1.rs:10:8
21+
|
22+
LL | fn foo<T>(x: (T, ())) -> Box<T> {
23+
| ^ required by the implicit `Sized` requirement on this type parameter in `foo`
24+
help: consider relaxing the implicit `Sized` restriction
25+
|
26+
LL | fn foo<T: ?Sized>(x: (T, ())) -> Box<T> {
27+
| ++++++++
28+
29+
error: aborting due to 2 previous errors
30+
31+
Some errors have detailed explanations: E0277, E0308.
32+
For more information about an error, try `rustc --explain E0277`.
Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
error[E0308]: mismatched types
2+
--> $DIR/fn-ret-trait-object-propagated-to-inputs-issue-149379-1.rs:16:33
3+
|
4+
LL | let _: Box<dyn Send> = foo(((), ()));
5+
| ^^ expected trait object, found `()`
6+
|
7+
= note: expected trait object `dyn Send`
8+
found unit type `()`
9+
10+
error[E0277]: the size for values of type `dyn Send` cannot be known at compilation time
11+
--> $DIR/fn-ret-trait-object-propagated-to-inputs-issue-149379-1.rs:16:32
12+
|
13+
LL | let _: Box<dyn Send> = foo(((), ()));
14+
| --- ^^^^^^^^ doesn't have a size known at compile-time
15+
| |
16+
| required by a bound introduced by this call
17+
|
18+
= help: the trait `Sized` is not implemented for `dyn Send`
19+
note: required by an implicit `Sized` bound in `foo`
20+
--> $DIR/fn-ret-trait-object-propagated-to-inputs-issue-149379-1.rs:10:8
21+
|
22+
LL | fn foo<T>(x: (T, ())) -> Box<T> {
23+
| ^ required by the implicit `Sized` requirement on this type parameter in `foo`
24+
help: consider relaxing the implicit `Sized` restriction
25+
|
26+
LL | fn foo<T: ?Sized>(x: (T, ())) -> Box<T> {
27+
| ++++++++
28+
29+
error: aborting due to 2 previous errors
30+
31+
Some errors have detailed explanations: E0277, E0308.
32+
For more information about an error, try `rustc --explain E0277`.
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
//@ revisions: current next
2+
//@ ignore-compare-mode-next-solver (explicit revisions)
3+
//@[next] compile-flags: -Znext-solver
4+
5+
// FIXME(#149379): This should pass, but fails due to fudged expactation
6+
// types which are potentially not well-formed or for whom the function
7+
// where-bounds don't actually hold. And this results in weird bugs when
8+
// later treating these expectations as if they were actually correct..
9+
10+
fn foo<T>(x: (T, ())) -> Box<T> {
11+
Box::new(x.0)
12+
}
13+
14+
fn main() {
15+
// Uses expectation as its struct tail is sized, resulting in `(dyn Send, ())`
16+
let _: Box<dyn Send> = foo(((), ()));
17+
//~^ ERROR mismatched types
18+
//~| ERROR the size for values of type `dyn Send` cannot be known at compilation time
19+
}
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
error[E0277]: the size for values of type `dyn Send` cannot be known at compilation time
2+
--> $DIR/fn-ret-trait-object-propagated-to-inputs-issue-149379-2.rs:15:38
3+
|
4+
LL | let _: Box<dyn Send> = sized_box(Box::new(1));
5+
| --------- ^^^^^^^^^^^ doesn't have a size known at compile-time
6+
| |
7+
| required by a bound introduced by this call
8+
|
9+
= help: the trait `Sized` is not implemented for `dyn Send`
10+
note: required by an implicit `Sized` bound in `sized_box`
11+
--> $DIR/fn-ret-trait-object-propagated-to-inputs-issue-149379-2.rs:10:14
12+
|
13+
LL | fn sized_box<T>(x: Box<T>) -> Box<T> {
14+
| ^ required by the implicit `Sized` requirement on this type parameter in `sized_box`
15+
help: consider relaxing the implicit `Sized` restriction
16+
|
17+
LL | fn sized_box<T: ?Sized>(x: Box<T>) -> Box<T> {
18+
| ++++++++
19+
20+
error: aborting due to 1 previous error
21+
22+
For more information about this error, try `rustc --explain E0277`.
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
error[E0277]: the size for values of type `dyn Send` cannot be known at compilation time
2+
--> $DIR/fn-ret-trait-object-propagated-to-inputs-issue-149379-2.rs:15:38
3+
|
4+
LL | let _: Box<dyn Send> = sized_box(Box::new(1));
5+
| --------- ^^^^^^^^^^^ doesn't have a size known at compile-time
6+
| |
7+
| required by a bound introduced by this call
8+
|
9+
= help: the trait `Sized` is not implemented for `dyn Send`
10+
note: required by an implicit `Sized` bound in `sized_box`
11+
--> $DIR/fn-ret-trait-object-propagated-to-inputs-issue-149379-2.rs:10:14
12+
|
13+
LL | fn sized_box<T>(x: Box<T>) -> Box<T> {
14+
| ^ required by the implicit `Sized` requirement on this type parameter in `sized_box`
15+
help: consider relaxing the implicit `Sized` restriction
16+
|
17+
LL | fn sized_box<T: ?Sized>(x: Box<T>) -> Box<T> {
18+
| ++++++++
19+
20+
error: aborting due to 1 previous error
21+
22+
For more information about this error, try `rustc --explain E0277`.
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
//@ revisions: current next
2+
//@ ignore-compare-mode-next-solver (explicit revisions)
3+
//@[next] compile-flags: -Znext-solver
4+
5+
// FIXME(#149379): This should pass, but fails due to fudged expactation
6+
// types which are potentially not well-formed or for whom the function
7+
// where-bounds don't actually hold. And this results in weird bugs when
8+
// later treating these expectations as if they were actually correct..
9+
10+
fn sized_box<T>(x: Box<T>) -> Box<T> {
11+
x
12+
}
13+
14+
fn main() {
15+
let _: Box<dyn Send> = sized_box(Box::new(1));
16+
//~^ ERROR the size for values of type `dyn Send` cannot be known at compilation time
17+
}
Lines changed: 87 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,87 @@
1+
error[E0277]: the size for values of type `dyn Send` cannot be known at compilation time
2+
--> $DIR/fn-ret-trait-object-propagated-to-inputs-issue-149379-3.rs:32:55
3+
|
4+
LL | let _: Box<dyn Send> = field_to_box1(Foo { field: 1, tail: () });
5+
| ^ doesn't have a size known at compile-time
6+
|
7+
= help: the trait `Sized` is not implemented for `dyn Send`
8+
note: required by an implicit `Sized` bound in `Foo`
9+
--> $DIR/fn-ret-trait-object-propagated-to-inputs-issue-149379-3.rs:10:12
10+
|
11+
LL | struct Foo<T> {
12+
| ^ required by the implicit `Sized` requirement on this type parameter in `Foo`
13+
help: you could relax the implicit `Sized` bound on `T` if it were used through indirection like `&T` or `Box<T>`
14+
--> $DIR/fn-ret-trait-object-propagated-to-inputs-issue-149379-3.rs:10:12
15+
|
16+
LL | struct Foo<T> {
17+
| ^ this could be changed to `T: ?Sized`...
18+
LL | field: T,
19+
| - ...if indirection were used here: `Box<T>`
20+
21+
error[E0308]: mismatched types
22+
--> $DIR/fn-ret-trait-object-propagated-to-inputs-issue-149379-3.rs:32:55
23+
|
24+
LL | let _: Box<dyn Send> = field_to_box1(Foo { field: 1, tail: () });
25+
| ^ expected trait object, found integer
26+
|
27+
= note: expected trait object `dyn Send`
28+
found type `{integer}`
29+
30+
error[E0277]: the size for values of type `dyn Send` cannot be known at compilation time
31+
--> $DIR/fn-ret-trait-object-propagated-to-inputs-issue-149379-3.rs:32:42
32+
|
33+
LL | let _: Box<dyn Send> = field_to_box1(Foo { field: 1, tail: () });
34+
| ------------- ^^^^^^^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time
35+
| |
36+
| required by a bound introduced by this call
37+
|
38+
= help: the trait `Sized` is not implemented for `dyn Send`
39+
note: required by an implicit `Sized` bound in `field_to_box1`
40+
--> $DIR/fn-ret-trait-object-propagated-to-inputs-issue-149379-3.rs:19:18
41+
|
42+
LL | fn field_to_box1<T>(x: Foo<T>) -> Box<T> {
43+
| ^ required by the implicit `Sized` requirement on this type parameter in `field_to_box1`
44+
help: consider relaxing the implicit `Sized` restriction
45+
|
46+
LL | fn field_to_box1<T: ?Sized>(x: Foo<T>) -> Box<T> {
47+
| ++++++++
48+
49+
error[E0277]: the size for values of type `dyn Send` cannot be known at compilation time
50+
--> $DIR/fn-ret-trait-object-propagated-to-inputs-issue-149379-3.rs:36:38
51+
|
52+
LL | let _: &dyn Send = field_to_box2(&Bar { field: 1 });
53+
| ------------- ^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time
54+
| |
55+
| required by a bound introduced by this call
56+
|
57+
= help: the trait `Sized` is not implemented for `dyn Send`
58+
note: required by an implicit `Sized` bound in `field_to_box2`
59+
--> $DIR/fn-ret-trait-object-propagated-to-inputs-issue-149379-3.rs:23:18
60+
|
61+
LL | fn field_to_box2<T>(x: &Bar<T>) -> &T {
62+
| ^ required by the implicit `Sized` requirement on this type parameter in `field_to_box2`
63+
help: consider relaxing the implicit `Sized` restriction
64+
|
65+
LL | fn field_to_box2<T: ?Sized>(x: &Bar<T>) -> &T {
66+
| ++++++++
67+
68+
error[E0308]: mismatched types
69+
--> $DIR/fn-ret-trait-object-propagated-to-inputs-issue-149379-3.rs:38:38
70+
|
71+
LL | let _: &dyn Send = field_to_box3(&(1,));
72+
| ------------- ^^^^^ expected `&(dyn Send,)`, found `&({integer},)`
73+
| |
74+
| arguments to this function are incorrect
75+
|
76+
= note: expected reference `&(dyn Send,)`
77+
found reference `&({integer},)`
78+
note: function defined here
79+
--> $DIR/fn-ret-trait-object-propagated-to-inputs-issue-149379-3.rs:27:4
80+
|
81+
LL | fn field_to_box3<T>(x: &(T,)) -> &T {
82+
| ^^^^^^^^^^^^^ --------
83+
84+
error: aborting due to 5 previous errors
85+
86+
Some errors have detailed explanations: E0277, E0308.
87+
For more information about an error, try `rustc --explain E0277`.
Lines changed: 87 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,87 @@
1+
error[E0277]: the size for values of type `dyn Send` cannot be known at compilation time
2+
--> $DIR/fn-ret-trait-object-propagated-to-inputs-issue-149379-3.rs:32:55
3+
|
4+
LL | let _: Box<dyn Send> = field_to_box1(Foo { field: 1, tail: () });
5+
| ^ doesn't have a size known at compile-time
6+
|
7+
= help: the trait `Sized` is not implemented for `dyn Send`
8+
note: required by an implicit `Sized` bound in `Foo`
9+
--> $DIR/fn-ret-trait-object-propagated-to-inputs-issue-149379-3.rs:10:12
10+
|
11+
LL | struct Foo<T> {
12+
| ^ required by the implicit `Sized` requirement on this type parameter in `Foo`
13+
help: you could relax the implicit `Sized` bound on `T` if it were used through indirection like `&T` or `Box<T>`
14+
--> $DIR/fn-ret-trait-object-propagated-to-inputs-issue-149379-3.rs:10:12
15+
|
16+
LL | struct Foo<T> {
17+
| ^ this could be changed to `T: ?Sized`...
18+
LL | field: T,
19+
| - ...if indirection were used here: `Box<T>`
20+
21+
error[E0308]: mismatched types
22+
--> $DIR/fn-ret-trait-object-propagated-to-inputs-issue-149379-3.rs:32:55
23+
|
24+
LL | let _: Box<dyn Send> = field_to_box1(Foo { field: 1, tail: () });
25+
| ^ expected trait object, found integer
26+
|
27+
= note: expected trait object `dyn Send`
28+
found type `{integer}`
29+
30+
error[E0277]: the size for values of type `dyn Send` cannot be known at compilation time
31+
--> $DIR/fn-ret-trait-object-propagated-to-inputs-issue-149379-3.rs:32:42
32+
|
33+
LL | let _: Box<dyn Send> = field_to_box1(Foo { field: 1, tail: () });
34+
| ------------- ^^^^^^^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time
35+
| |
36+
| required by a bound introduced by this call
37+
|
38+
= help: the trait `Sized` is not implemented for `dyn Send`
39+
note: required by an implicit `Sized` bound in `field_to_box1`
40+
--> $DIR/fn-ret-trait-object-propagated-to-inputs-issue-149379-3.rs:19:18
41+
|
42+
LL | fn field_to_box1<T>(x: Foo<T>) -> Box<T> {
43+
| ^ required by the implicit `Sized` requirement on this type parameter in `field_to_box1`
44+
help: consider relaxing the implicit `Sized` restriction
45+
|
46+
LL | fn field_to_box1<T: ?Sized>(x: Foo<T>) -> Box<T> {
47+
| ++++++++
48+
49+
error[E0277]: the size for values of type `dyn Send` cannot be known at compilation time
50+
--> $DIR/fn-ret-trait-object-propagated-to-inputs-issue-149379-3.rs:36:38
51+
|
52+
LL | let _: &dyn Send = field_to_box2(&Bar { field: 1 });
53+
| ------------- ^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time
54+
| |
55+
| required by a bound introduced by this call
56+
|
57+
= help: the trait `Sized` is not implemented for `dyn Send`
58+
note: required by an implicit `Sized` bound in `field_to_box2`
59+
--> $DIR/fn-ret-trait-object-propagated-to-inputs-issue-149379-3.rs:23:18
60+
|
61+
LL | fn field_to_box2<T>(x: &Bar<T>) -> &T {
62+
| ^ required by the implicit `Sized` requirement on this type parameter in `field_to_box2`
63+
help: consider relaxing the implicit `Sized` restriction
64+
|
65+
LL | fn field_to_box2<T: ?Sized>(x: &Bar<T>) -> &T {
66+
| ++++++++
67+
68+
error[E0308]: mismatched types
69+
--> $DIR/fn-ret-trait-object-propagated-to-inputs-issue-149379-3.rs:38:38
70+
|
71+
LL | let _: &dyn Send = field_to_box3(&(1,));
72+
| ------------- ^^^^^ expected `&(dyn Send,)`, found `&({integer},)`
73+
| |
74+
| arguments to this function are incorrect
75+
|
76+
= note: expected reference `&(dyn Send,)`
77+
found reference `&({integer},)`
78+
note: function defined here
79+
--> $DIR/fn-ret-trait-object-propagated-to-inputs-issue-149379-3.rs:27:4
80+
|
81+
LL | fn field_to_box3<T>(x: &(T,)) -> &T {
82+
| ^^^^^^^^^^^^^ --------
83+
84+
error: aborting due to 5 previous errors
85+
86+
Some errors have detailed explanations: E0277, E0308.
87+
For more information about an error, try `rustc --explain E0277`.

0 commit comments

Comments
 (0)