Skip to content

Always structurally resolve coercion target #131483

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
Closed
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
2 changes: 1 addition & 1 deletion compiler/rustc_hir_typeck/src/expr.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1860,8 +1860,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
base_expr: &'tcx Option<&'tcx hir::Expr<'tcx>>,
) {
let tcx = self.tcx;
self.select_obligations_where_possible(|_| {});

let adt_ty = self.try_structurally_resolve_type(span, adt_ty);
let adt_ty_hint = expected.only_has_type(self).and_then(|expected| {
self.fudge_inference_if_ok(|| {
let ocx = ObligationCtxt::new(self);
Expand Down
4 changes: 3 additions & 1 deletion compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs
Original file line number Diff line number Diff line change
Expand Up @@ -208,11 +208,13 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
);
}

// Guide inference on the formal output ty if necessary.
self.select_obligations_where_possible(|_| {});

// 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
// is because the inference guidance here is only speculative.
let formal_output = self.resolve_vars_with_obligations(formal_output);
let expected_input_tys: Option<Vec<_>> = expectation
.only_has_type(self)
.and_then(|expected_output| {
Expand Down
7 changes: 5 additions & 2 deletions compiler/rustc_hir_typeck/src/op.rs
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
) -> Ty<'tcx> {
let (lhs_ty, rhs_ty, return_ty) =
self.check_overloaded_binop(expr, lhs, rhs, op, IsAssign::Yes, expected);
let lhs_ty = self.try_structurally_resolve_type(lhs.span, lhs_ty);
let rhs_ty = self.try_structurally_resolve_type(rhs.span, rhs_ty);

let ty =
if !lhs_ty.is_ty_var() && !rhs_ty.is_ty_var() && is_builtin_binop(lhs_ty, rhs_ty, op) {
Expand Down Expand Up @@ -231,7 +233,6 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
self.check_expr(lhs_expr)
}
};
let lhs_ty = self.resolve_vars_with_obligations(lhs_ty);

// N.B., as we have not yet type-checked the RHS, we don't have the
// type at hand. Make a variable to represent it. The whole reason
Expand All @@ -250,7 +251,6 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {

// see `NB` above
let rhs_ty = self.check_expr_coercible_to_type(rhs_expr, rhs_ty_var, Some(lhs_expr));
let rhs_ty = self.resolve_vars_with_obligations(rhs_ty);

let return_ty = match result {
Ok(method) => {
Expand Down Expand Up @@ -296,6 +296,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
Ty::new_misc_error(self.tcx)
}
Err(errors) => {
let lhs_ty = self.try_structurally_resolve_type(lhs_expr.span, lhs_ty);
let rhs_ty = self.try_structurally_resolve_type(rhs_expr.span, rhs_ty);

let (_, trait_def_id) =
lang_item_for_op(self.tcx, Op::Binary(op, is_assign), op.span);
let missing_trait = trait_def_id
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,14 @@ LL | pub struct InvariantRef<'a, T: ?Sized>(&'a T, PhantomData<&'a mut &'a T>);
LL | pub const NEW: Self = InvariantRef::new(&());
| ^^^ function or associated item not found in `InvariantRef<'_, _>`

error[E0277]: the trait bound `u8: Trait` is not satisfied
--> $DIR/correct_body_owner_parent_found_in_diagnostics.rs:22:12
|
LL | reuse <u8 as Trait>::{foo, bar, meh} { &const { InvariantRef::<'a>::NEW } }
| ^^ the trait `Trait` is not implemented for `u8`
|
= help: the trait `Trait` is implemented for `Z`

error[E0308]: mismatched types
--> $DIR/correct_body_owner_parent_found_in_diagnostics.rs:22:53
|
Expand All @@ -68,6 +76,7 @@ LL | reuse <u8 as Trait>::{foo, bar, meh} { &const { InvariantRef::<'a>::NEW
| ^^ the trait `Trait` is not implemented for `u8`
|
= help: the trait `Trait` is implemented for `Z`
= note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`

error[E0308]: mismatched types
--> $DIR/correct_body_owner_parent_found_in_diagnostics.rs:22:53
Expand Down Expand Up @@ -98,15 +107,6 @@ LL | reuse <u8 as Trait>::{foo, bar, meh} { &const { InvariantRef::<'a>::NEW
found struct `InvariantRef<'_, ()>`
= note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`

error[E0277]: the trait bound `u8: Trait` is not satisfied
--> $DIR/correct_body_owner_parent_found_in_diagnostics.rs:22:12
|
LL | reuse <u8 as Trait>::{foo, bar, meh} { &const { InvariantRef::<'a>::NEW } }
| ^^ the trait `Trait` is not implemented for `u8`
|
= help: the trait `Trait` is implemented for `Z`
= note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`

error: aborting due to 10 previous errors

Some errors have detailed explanations: E0261, E0277, E0308, E0599.
Expand Down
10 changes: 5 additions & 5 deletions tests/ui/issues/issue-50781.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -15,10 +15,10 @@ LL | fn foo(&self) where Self: Trait;
= help: only type `()` implements the trait, consider using it directly instead

error[E0038]: the trait `X` cannot be made into an object
--> $DIR/issue-50781.rs:16:23
--> $DIR/issue-50781.rs:16:6
|
LL | <dyn X as X>::foo(&());
| ^^^ `X` cannot be made into an object
| ^^^^^ `X` cannot be made into an object
|
note: for a trait to be "dyn-compatible" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety>
--> $DIR/issue-50781.rs:4:8
Expand All @@ -29,13 +29,12 @@ LL | fn foo(&self) where Self: Trait;
| ^^^ ...because method `foo` references the `Self` type in its `where` clause
= help: consider moving `foo` to another trait
= help: only type `()` implements the trait, consider using it directly instead
= note: required for the cast from `&()` to `&dyn X`

error[E0038]: the trait `X` cannot be made into an object
--> $DIR/issue-50781.rs:16:6
--> $DIR/issue-50781.rs:16:23
|
LL | <dyn X as X>::foo(&());
| ^^^^^ `X` cannot be made into an object
| ^^^ `X` cannot be made into an object
|
note: for a trait to be "dyn-compatible" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety>
--> $DIR/issue-50781.rs:4:8
Expand All @@ -46,6 +45,7 @@ LL | fn foo(&self) where Self: Trait;
| ^^^ ...because method `foo` references the `Self` type in its `where` clause
= help: consider moving `foo` to another trait
= help: only type `()` implements the trait, consider using it directly instead
= note: required for the cast from `&()` to `&dyn X`

error: aborting due to 3 previous errors

Expand Down
8 changes: 4 additions & 4 deletions tests/ui/overloaded/overloaded-calls-nontuple.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -39,17 +39,17 @@ LL | self.call_mut(z)
note: required by a bound in `call_mut`
--> $SRC_DIR/core/src/ops/function.rs:LL:COL

error[E0059]: cannot use call notation; the first type parameter for the function trait is neither a tuple nor unit
error[E0277]: `isize` is not a tuple
--> $DIR/overloaded-calls-nontuple.rs:29:10
|
LL | drop(s(3))
| ^^^^
| ^^^^ the trait `Tuple` is not implemented for `isize`

error[E0277]: `isize` is not a tuple
error[E0059]: cannot use call notation; the first type parameter for the function trait is neither a tuple nor unit
--> $DIR/overloaded-calls-nontuple.rs:29:10
|
LL | drop(s(3))
| ^^^^ the trait `Tuple` is not implemented for `isize`
| ^^^^

error: aborting due to 7 previous errors

Expand Down
8 changes: 4 additions & 4 deletions tests/ui/suggestions/fn-trait-notation.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -37,17 +37,17 @@ LL | F: Fn<i32, Output = i32>,
note: required by a bound in `Fn`
--> $SRC_DIR/core/src/ops/function.rs:LL:COL

error[E0059]: cannot use call notation; the first type parameter for the function trait is neither a tuple nor unit
error[E0277]: `i32` is not a tuple
--> $DIR/fn-trait-notation.rs:9:5
|
LL | f(3);
| ^^^^
| ^^^^ the trait `Tuple` is not implemented for `i32`

error[E0277]: `i32` is not a tuple
error[E0059]: cannot use call notation; the first type parameter for the function trait is neither a tuple nor unit
--> $DIR/fn-trait-notation.rs:9:5
|
LL | f(3);
| ^^^^ the trait `Tuple` is not implemented for `i32`
| ^^^^

error[E0308]: mismatched types
--> $DIR/fn-trait-notation.rs:17:5
Expand Down
4 changes: 2 additions & 2 deletions tests/ui/traits/next-solver/more-object-bound.stderr
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
error[E0271]: type mismatch resolving `<dyn Trait<A = A, B = B> as SuperTrait>::A == B`
--> $DIR/more-object-bound.rs:12:5
--> $DIR/more-object-bound.rs:12:17
|
LL | fn transmute<A, B>(x: A) -> B {
| - -
Expand All @@ -9,7 +9,7 @@ LL | fn transmute<A, B>(x: A) -> B {
| found type parameter
| expected type parameter
LL | foo::<A, B, dyn Trait<A = A, B = B>>(x)
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected type parameter `A`, found type parameter `B`
| ^^^^^^^^^^^^^^^^^^^^^^^ expected type parameter `A`, found type parameter `B`
|
= note: expected type parameter `A`
found type parameter `B`
Expand Down
Loading