Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
83 changes: 49 additions & 34 deletions compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs
Original file line number Diff line number Diff line change
Expand Up @@ -235,6 +235,38 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
self.check_place_expr_if_unsized(fn_input_ty, arg_expr);
}

let formal_input_tys_ns;
let formal_input_tys = if self.next_trait_solver() {
// In the new solver, the normalizations are done lazily.
// Because of this, if we encounter unnormalized alias types inside this
// fudge scope, we might lose the relationships between them and other vars
// when fudging inference variables created here.
// So, we utilize generalization to normalize aliases by adding a new
// inference var and equating it with the type we want to pull out of the
// fudge scope.
formal_input_tys_ns = formal_input_tys
.iter()
.map(|&ty| {
// If we replace a (unresolved) inference var with a new inference
// var, it will be eventually resolved to itself and this will
// weaken type inferences as the new inference var will be fudged
// out and lose all relationships with other vars while the former
// will not be fudged.
if ty.is_ty_var() {
return ty;
}

let generalized_ty = self.next_ty_var(call_span);
self.demand_eqtype(call_span, ty, generalized_ty);
generalized_ty
})
.collect_vec();

formal_input_tys_ns.as_slice()
} else {
formal_input_tys
};

// First, let's unify the formal method signature with the expectation eagerly.
// We use this to guide coercion inference; it's output is "fudged" which means
// any remaining type variables are assigned to new, unrelated variables. This
Expand All @@ -257,39 +289,6 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
// No argument expectations are produced if unification fails.
let origin = self.misc(call_span);
ocx.sup(&origin, self.param_env, expected_output, formal_output)?;

let formal_input_tys_ns;
let formal_input_tys = if self.next_trait_solver() {
// In the new solver, the normalizations are done lazily.
// Because of this, if we encounter unnormalized alias types inside this
// fudge scope, we might lose the relationships between them and other vars
// when fudging inference variables created here.
// So, we utilize generalization to normalize aliases by adding a new
// inference var and equating it with the type we want to pull out of the
// fudge scope.
formal_input_tys_ns = formal_input_tys
.iter()
.map(|&ty| {
// If we replace a (unresolved) inference var with a new inference
// var, it will be eventually resolved to itself and this will
// weaken type inferences as the new inference var will be fudged
// out and lose all relationships with other vars while the former
// will not be fudged.
if ty.is_ty_var() {
return ty;
}

let generalized_ty = self.next_ty_var(call_span);
ocx.eq(&origin, self.param_env, ty, generalized_ty).unwrap();
generalized_ty
})
.collect_vec();

formal_input_tys_ns.as_slice()
} else {
formal_input_tys
};

if !ocx.try_evaluate_obligations().is_empty() {
return Err(TypeError::Mismatch);
}
Expand All @@ -305,7 +304,23 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
})
.ok()
})
.unwrap_or_default();
.unwrap_or_default()
.filter(|expected_input_tys: &Vec<Ty<'_>>| {
// Check the well-formedness of expected input tys, as using ill-formed
// expectation may cause type inference errors.
self.probe(|_| {
let ocx = ObligationCtxt::new(self);
for &ty in expected_input_tys {
ocx.register_obligation(traits::Obligation::new(
self.tcx,
self.misc(call_span),
self.param_env,
ty::ClauseKind::WellFormed(ty.into()),
));
}
ocx.try_evaluate_obligations().is_empty()
})
});

let mut err_code = E0061;

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
error[E0277]: the size for values of type `[{integer}]` cannot be known at compilation time
--> $DIR/expectated-input-not-satisfying-fn-bounds-issue-149881.rs:15:24
|
LL | <[_]>::into_vec(id(Box::new([0, 1, 2])));
| -- ^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time
| |
| required by a bound introduced by this call
|
= help: the trait `Sized` is not implemented for `[{integer}]`
note: required by an implicit `Sized` bound in `id`
--> $DIR/expectated-input-not-satisfying-fn-bounds-issue-149881.rs:10:7
|
LL | fn id<T>(x: Box<T>) -> Box<T> {
| ^ required by the implicit `Sized` requirement on this type parameter in `id`
help: consider relaxing the implicit `Sized` restriction
|
LL | fn id<T: ?Sized>(x: Box<T>) -> Box<T> {
| ++++++++

error: aborting due to 1 previous error

For more information about this error, try `rustc --explain E0277`.
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
error[E0277]: the size for values of type `[{integer}]` cannot be known at compilation time
--> $DIR/expectated-input-not-satisfying-fn-bounds-issue-149881.rs:15:24
|
LL | <[_]>::into_vec(id(Box::new([0, 1, 2])));
| -- ^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time
| |
| required by a bound introduced by this call
|
= help: the trait `Sized` is not implemented for `[{integer}]`
note: required by an implicit `Sized` bound in `id`
--> $DIR/expectated-input-not-satisfying-fn-bounds-issue-149881.rs:10:7
|
LL | fn id<T>(x: Box<T>) -> Box<T> {
| ^ required by the implicit `Sized` requirement on this type parameter in `id`
help: consider relaxing the implicit `Sized` restriction
|
LL | fn id<T: ?Sized>(x: Box<T>) -> Box<T> {
| ++++++++

error: aborting due to 1 previous error

For more information about this error, try `rustc --explain E0277`.
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
//@ revisions: current next
//@ ignore-compare-mode-next-solver (explicit revisions)
//@[next] compile-flags: -Znext-solver

// FIXME(#149379): This should pass, but fails due to fudged expactation
// types which are potentially not well-formed or for whom the function
// where-bounds don't actually hold. And this results in weird bugs when
// later treating these expectations as if they were actually correct..

fn id<T>(x: Box<T>) -> Box<T> {
x
}

fn main() {
<[_]>::into_vec(id(Box::new([0, 1, 2])));
//~^ ERROR: the size for values of type `[{integer}]` cannot be known at compilation time
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
error[E0277]: `dyn Trait + Send` cannot be unpinned
--> $DIR/expectated-input-not-satisfying-fn-bounds-issue-89299.rs:20:27
|
LL | let _x = Foo(Pin::new(&mut a));
| -------- ^^^^^^ the trait `Unpin` is not implemented for `dyn Trait + Send`
| |
| required by a bound introduced by this call
|
= note: consider using the `pin!` macro
consider using `Box::pin` if you need to access the pinned value outside of the current scope
note: required by a bound in `Pin::<Ptr>::new`
--> $SRC_DIR/core/src/pin.rs:LL:COL

error: aborting due to 1 previous error

For more information about this error, try `rustc --explain E0277`.
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
error[E0277]: `dyn Trait + Send` cannot be unpinned
--> $DIR/expectated-input-not-satisfying-fn-bounds-issue-89299.rs:20:27
|
LL | let _x = Foo(Pin::new(&mut a));
| -------- ^^^^^^ the trait `Unpin` is not implemented for `dyn Trait + Send`
| |
| required by a bound introduced by this call
|
= note: consider using the `pin!` macro
consider using `Box::pin` if you need to access the pinned value outside of the current scope
note: required by a bound in `Pin::<Ptr>::new`
--> $SRC_DIR/core/src/pin.rs:LL:COL

error: aborting due to 1 previous error

For more information about this error, try `rustc --explain E0277`.
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
//@ revisions: current next
//@ ignore-compare-mode-next-solver (explicit revisions)
//@[next] compile-flags: -Znext-solver

// FIXME(#149379): This should pass, but fails due to fudged expactation
// types which are potentially not well-formed or for whom the function
// where-bounds don't actually hold. And this results in weird bugs when
// later treating these expectations as if they were actually correct..

use std::pin::Pin;

trait Trait {}

impl Trait for i32 {}

struct Foo<'a>(Pin<&'a mut (dyn Trait + Send)>);

fn main() {
let mut a = 1;
let _x = Foo(Pin::new(&mut a));
//~^ ERROR: `dyn Trait + Send` cannot be unpinned
}

This file was deleted.

This file was deleted.

Original file line number Diff line number Diff line change
@@ -1,11 +1,9 @@
//@ revisions: current next
//@ ignore-compare-mode-next-solver (explicit revisions)
//@[next] compile-flags: -Znext-solver
//@ check-pass

// FIXME(#149379): This should pass, but fails due to fudged expactation
// types which are potentially not well-formed or for whom the function
// where-bounds don't actually hold. And this results in weird bugs when
// later treating these expectations as if they were actually correct..
// A regression test for https://github.com/rust-lang/rust/issues/149379.

fn foo<T>(x: (T, ())) -> Box<T> {
Box::new(x.0)
Expand All @@ -14,6 +12,4 @@ fn foo<T>(x: (T, ())) -> Box<T> {
fn main() {
// Uses expectation as its struct tail is sized, resulting in `(dyn Send, ())`
let _: Box<dyn Send> = foo(((), ()));
//~^ ERROR mismatched types
//~| ERROR the size for values of type `dyn Send` cannot be known at compilation time
}
Original file line number Diff line number Diff line change
@@ -1,72 +1,5 @@
error[E0277]: the size for values of type `dyn Send` cannot be known at compilation time
--> $DIR/fn-ret-trait-object-propagated-to-inputs-issue-149379-3.rs:32:55
|
LL | let _: Box<dyn Send> = field_to_box1(Foo { field: 1, tail: () });
| ^ doesn't have a size known at compile-time
|
= help: the trait `Sized` is not implemented for `dyn Send`
note: required by an implicit `Sized` bound in `Foo`
--> $DIR/fn-ret-trait-object-propagated-to-inputs-issue-149379-3.rs:10:12
|
LL | struct Foo<T> {
| ^ required by the implicit `Sized` requirement on this type parameter in `Foo`
help: you could relax the implicit `Sized` bound on `T` if it were used through indirection like `&T` or `Box<T>`
--> $DIR/fn-ret-trait-object-propagated-to-inputs-issue-149379-3.rs:10:12
|
LL | struct Foo<T> {
| ^ this could be changed to `T: ?Sized`...
LL | field: T,
| - ...if indirection were used here: `Box<T>`

error[E0308]: mismatched types
--> $DIR/fn-ret-trait-object-propagated-to-inputs-issue-149379-3.rs:32:55
|
LL | let _: Box<dyn Send> = field_to_box1(Foo { field: 1, tail: () });
| ^ expected trait object, found integer
|
= note: expected trait object `dyn Send`
found type `{integer}`

error[E0277]: the size for values of type `dyn Send` cannot be known at compilation time
--> $DIR/fn-ret-trait-object-propagated-to-inputs-issue-149379-3.rs:32:42
|
LL | let _: Box<dyn Send> = field_to_box1(Foo { field: 1, tail: () });
| ------------- ^^^^^^^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time
| |
| required by a bound introduced by this call
|
= help: the trait `Sized` is not implemented for `dyn Send`
note: required by an implicit `Sized` bound in `field_to_box1`
--> $DIR/fn-ret-trait-object-propagated-to-inputs-issue-149379-3.rs:19:18
|
LL | fn field_to_box1<T>(x: Foo<T>) -> Box<T> {
| ^ required by the implicit `Sized` requirement on this type parameter in `field_to_box1`
help: consider relaxing the implicit `Sized` restriction
|
LL | fn field_to_box1<T: ?Sized>(x: Foo<T>) -> Box<T> {
| ++++++++

error[E0277]: the size for values of type `dyn Send` cannot be known at compilation time
--> $DIR/fn-ret-trait-object-propagated-to-inputs-issue-149379-3.rs:36:38
|
LL | let _: &dyn Send = field_to_box2(&Bar { field: 1 });
| ------------- ^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time
| |
| required by a bound introduced by this call
|
= help: the trait `Sized` is not implemented for `dyn Send`
note: required by an implicit `Sized` bound in `field_to_box2`
--> $DIR/fn-ret-trait-object-propagated-to-inputs-issue-149379-3.rs:23:18
|
LL | fn field_to_box2<T>(x: &Bar<T>) -> &T {
| ^ required by the implicit `Sized` requirement on this type parameter in `field_to_box2`
help: consider relaxing the implicit `Sized` restriction
|
LL | fn field_to_box2<T: ?Sized>(x: &Bar<T>) -> &T {
| ++++++++

error[E0308]: mismatched types
--> $DIR/fn-ret-trait-object-propagated-to-inputs-issue-149379-3.rs:38:38
--> $DIR/fn-ret-trait-object-propagated-to-inputs-issue-149379-3.rs:34:38
|
LL | let _: &dyn Send = field_to_box3(&(1,));
| ------------- ^^^^^ expected `&(dyn Send,)`, found `&({integer},)`
Expand All @@ -81,7 +14,6 @@ note: function defined here
LL | fn field_to_box3<T>(x: &(T,)) -> &T {
| ^^^^^^^^^^^^^ --------

error: aborting due to 5 previous errors
error: aborting due to 1 previous error

Some errors have detailed explanations: E0277, E0308.
For more information about an error, try `rustc --explain E0277`.
For more information about this error, try `rustc --explain E0308`.
Loading