about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--compiler/rustc_hir_typeck/src/_match.rs3
-rw-r--r--compiler/rustc_hir_typeck/src/expectation.rs8
-rw-r--r--compiler/rustc_hir_typeck/src/expr.rs10
-rw-r--r--compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs15
-rw-r--r--tests/ui/impl-trait/auto-trait-selection-freeze.next.stderr21
-rw-r--r--tests/ui/impl-trait/auto-trait-selection.next.stderr21
-rw-r--r--tests/ui/traits/next-solver/typeck/resolve-expectations.rs26
-rw-r--r--tests/ui/traits/next-solver/typeck/structurally-resolve-in-resolve_for_branch.rs8
8 files changed, 62 insertions, 50 deletions
diff --git a/compiler/rustc_hir_typeck/src/_match.rs b/compiler/rustc_hir_typeck/src/_match.rs
index bfdf764d299..243313ee876 100644
--- a/compiler/rustc_hir_typeck/src/_match.rs
+++ b/compiler/rustc_hir_typeck/src/_match.rs
@@ -57,7 +57,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         // type in that case)
         let mut all_arms_diverge = Diverges::WarnedAlways;
 
-        let expected = orig_expected.adjust_for_branches(self);
+        let expected =
+            orig_expected.try_structurally_resolve_and_adjust_for_branches(self, expr.span);
         debug!(?expected);
 
         let mut coercion = {
diff --git a/compiler/rustc_hir_typeck/src/expectation.rs b/compiler/rustc_hir_typeck/src/expectation.rs
index 4653458b5dd..6d95b6917e2 100644
--- a/compiler/rustc_hir_typeck/src/expectation.rs
+++ b/compiler/rustc_hir_typeck/src/expectation.rs
@@ -39,10 +39,14 @@ impl<'a, 'tcx> Expectation<'tcx> {
     // an expected type. Otherwise, we might write parts of the type
     // when checking the 'then' block which are incompatible with the
     // 'else' branch.
-    pub(super) fn adjust_for_branches(&self, fcx: &FnCtxt<'a, 'tcx>) -> Expectation<'tcx> {
+    pub(super) fn try_structurally_resolve_and_adjust_for_branches(
+        &self,
+        fcx: &FnCtxt<'a, 'tcx>,
+        span: Span,
+    ) -> Expectation<'tcx> {
         match *self {
             ExpectHasType(ety) => {
-                let ety = fcx.shallow_resolve(ety);
+                let ety = fcx.try_structurally_resolve_type(span, ety);
                 if !ety.is_ty_var() { ExpectHasType(ety) } else { NoExpectation }
             }
             ExpectRvalueLikeUnsized(ety) => ExpectRvalueLikeUnsized(ety),
diff --git a/compiler/rustc_hir_typeck/src/expr.rs b/compiler/rustc_hir_typeck/src/expr.rs
index 4699b342cec..04c06169d33 100644
--- a/compiler/rustc_hir_typeck/src/expr.rs
+++ b/compiler/rustc_hir_typeck/src/expr.rs
@@ -628,7 +628,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         expr: &'tcx hir::Expr<'tcx>,
     ) -> Ty<'tcx> {
         let hint = expected.only_has_type(self).map_or(NoExpectation, |ty| {
-            match ty.kind() {
+            match self.try_structurally_resolve_type(expr.span, ty).kind() {
                 ty::Ref(_, ty, _) | ty::RawPtr(ty, _) => {
                     if oprnd.is_syntactic_place_expr() {
                         // Places may legitimately have unsized types.
@@ -1293,7 +1293,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         let cond_diverges = self.diverges.get();
         self.diverges.set(Diverges::Maybe);
 
-        let expected = orig_expected.adjust_for_branches(self);
+        let expected = orig_expected.try_structurally_resolve_and_adjust_for_branches(self, sp);
         let then_ty = self.check_expr_with_expectation(then_expr, expected);
         let then_diverges = self.diverges.get();
         self.diverges.set(Diverges::Maybe);
@@ -1354,8 +1354,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         rhs: &'tcx hir::Expr<'tcx>,
         span: Span,
     ) -> Ty<'tcx> {
-        let expected_ty = expected.coercion_target_type(self, expr.span);
-        if expected_ty == self.tcx.types.bool {
+        let expected_ty = expected.only_has_type(self);
+        if expected_ty == Some(self.tcx.types.bool) {
             let guar = self.expr_assign_expected_bool_error(expr, lhs, rhs, span);
             return Ty::new_error(self.tcx, guar);
         }
@@ -1639,7 +1639,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         let element_ty = if !args.is_empty() {
             let coerce_to = expected
                 .to_option(self)
-                .and_then(|uty| match *uty.kind() {
+                .and_then(|uty| match *self.try_structurally_resolve_type(expr.span, uty).kind() {
                     ty::Array(ty, _) | ty::Slice(ty) => Some(ty),
                     _ => None,
                 })
diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs
index 30c838b74af..44582390a4b 100644
--- a/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs
+++ b/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs
@@ -936,18 +936,17 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         // can be collated pretty easily if needed.
 
         // Next special case: if there is only one "Incompatible" error, just emit that
-        if let [
+        if let &[
             Error::Invalid(provided_idx, expected_idx, Compatibility::Incompatible(Some(err))),
         ] = &errors[..]
         {
-            let (formal_ty, expected_ty) = formal_and_expected_inputs[*expected_idx];
-            let (provided_ty, provided_arg_span) = provided_arg_tys[*provided_idx];
+            let (formal_ty, expected_ty) = formal_and_expected_inputs[expected_idx];
+            let (provided_ty, provided_arg_span) = provided_arg_tys[provided_idx];
             let trace = mk_trace(provided_arg_span, (formal_ty, expected_ty), provided_ty);
-            let mut err =
-                self.err_ctxt().report_and_explain_type_error(trace, self.param_env, *err);
+            let mut err = self.err_ctxt().report_and_explain_type_error(trace, self.param_env, err);
             self.emit_coerce_suggestions(
                 &mut err,
-                provided_args[*provided_idx],
+                provided_args[provided_idx],
                 provided_ty,
                 Expectation::rvalue_hint(self, expected_ty)
                     .only_has_type(self)
@@ -982,7 +981,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
             self.suggest_ptr_null_mut(
                 expected_ty,
                 provided_ty,
-                provided_args[*provided_idx],
+                provided_args[provided_idx],
                 &mut err,
             );
 
@@ -992,7 +991,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                 call_ident,
                 expected_ty,
                 provided_ty,
-                provided_args[*provided_idx],
+                provided_args[provided_idx],
                 is_method,
             );
 
diff --git a/tests/ui/impl-trait/auto-trait-selection-freeze.next.stderr b/tests/ui/impl-trait/auto-trait-selection-freeze.next.stderr
index 5caf0eb2fd4..54ceec0aff5 100644
--- a/tests/ui/impl-trait/auto-trait-selection-freeze.next.stderr
+++ b/tests/ui/impl-trait/auto-trait-selection-freeze.next.stderr
@@ -1,22 +1,9 @@
-error[E0283]: type annotations needed
-  --> $DIR/auto-trait-selection-freeze.rs:19:16
+error[E0284]: type annotations needed: cannot satisfy `impl Sized == _`
+  --> $DIR/auto-trait-selection-freeze.rs:19:5
    |
 LL |     if false { is_trait(foo()) } else { Default::default() }
-   |                ^^^^^^^^ ----- type must be known at this point
-   |                |
-   |                cannot infer type of the type parameter `T` declared on the function `is_trait`
-   |
-   = note: cannot satisfy `_: Trait<_>`
-note: required by a bound in `is_trait`
-  --> $DIR/auto-trait-selection-freeze.rs:11:16
-   |
-LL | fn is_trait<T: Trait<U>, U: Default>(_: T) -> U {
-   |                ^^^^^^^^ required by this bound in `is_trait`
-help: consider specifying the generic arguments
-   |
-LL |     if false { is_trait::<T, U>(foo()) } else { Default::default() }
-   |                        ++++++++
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ cannot satisfy `impl Sized == _`
 
 error: aborting due to 1 previous error
 
-For more information about this error, try `rustc --explain E0283`.
+For more information about this error, try `rustc --explain E0284`.
diff --git a/tests/ui/impl-trait/auto-trait-selection.next.stderr b/tests/ui/impl-trait/auto-trait-selection.next.stderr
index d34fdcc4496..7acb9fd41b7 100644
--- a/tests/ui/impl-trait/auto-trait-selection.next.stderr
+++ b/tests/ui/impl-trait/auto-trait-selection.next.stderr
@@ -1,22 +1,9 @@
-error[E0283]: type annotations needed
-  --> $DIR/auto-trait-selection.rs:15:16
+error[E0284]: type annotations needed: cannot satisfy `impl Sized == _`
+  --> $DIR/auto-trait-selection.rs:15:5
    |
 LL |     if false { is_trait(foo()) } else { Default::default() }
-   |                ^^^^^^^^ ----- type must be known at this point
-   |                |
-   |                cannot infer type of the type parameter `T` declared on the function `is_trait`
-   |
-   = note: cannot satisfy `_: Trait<_>`
-note: required by a bound in `is_trait`
-  --> $DIR/auto-trait-selection.rs:7:16
-   |
-LL | fn is_trait<T: Trait<U>, U: Default>(_: T) -> U {
-   |                ^^^^^^^^ required by this bound in `is_trait`
-help: consider specifying the generic arguments
-   |
-LL |     if false { is_trait::<T, U>(foo()) } else { Default::default() }
-   |                        ++++++++
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ cannot satisfy `impl Sized == _`
 
 error: aborting due to 1 previous error
 
-For more information about this error, try `rustc --explain E0283`.
+For more information about this error, try `rustc --explain E0284`.
diff --git a/tests/ui/traits/next-solver/typeck/resolve-expectations.rs b/tests/ui/traits/next-solver/typeck/resolve-expectations.rs
new file mode 100644
index 00000000000..d6b3816b9eb
--- /dev/null
+++ b/tests/ui/traits/next-solver/typeck/resolve-expectations.rs
@@ -0,0 +1,26 @@
+//@ check-pass
+//@ compile-flags: -Znext-solver
+
+trait Mirror {
+    type Assoc;
+}
+impl<T> Mirror for T {
+    type Assoc = T;
+}
+
+fn id<T>(t: T) -> T { t }
+
+trait Foo {}
+impl Foo for i32 {}
+impl Foo for u32 {}
+
+fn main() {
+    // Make sure we resolve expected pointee of addr-of.
+    id::<<&&dyn Foo as Mirror>::Assoc>(&id(&1));
+
+    // Make sure we resolve expected element of array.
+    id::<<[Box<dyn Foo>; 2] as Mirror>::Assoc>([Box::new(1i32), Box::new(1u32)]);
+
+    // Make sure we resolve expected element of tuple.
+    id::<<(Box<dyn Foo>,) as Mirror>::Assoc>((Box::new(1i32),));
+}
diff --git a/tests/ui/traits/next-solver/typeck/structurally-resolve-in-resolve_for_branch.rs b/tests/ui/traits/next-solver/typeck/structurally-resolve-in-resolve_for_branch.rs
new file mode 100644
index 00000000000..d406f3949a2
--- /dev/null
+++ b/tests/ui/traits/next-solver/typeck/structurally-resolve-in-resolve_for_branch.rs
@@ -0,0 +1,8 @@
+//@ compile-flags: -Znext-solver
+//@ check-pass
+
+pub fn repro() -> impl FnMut() {
+    if true { || () } else { || () }
+}
+
+fn main() {}