diff --git a/compiler/rustc_hir_typeck/src/_match.rs b/compiler/rustc_hir_typeck/src/_match.rs index bfdf764d299b4..49d1747723c08 100644 --- a/compiler/rustc_hir_typeck/src/_match.rs +++ b/compiler/rustc_hir_typeck/src/_match.rs @@ -57,7 +57,7 @@ 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.adjust_for_branches(self, expr.span); debug!(?expected); let mut coercion = { @@ -86,7 +86,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { let arm_ty = self.check_expr_with_expectation(arm.body, expected); all_arms_diverge &= self.diverges.get(); let tail_defines_return_position_impl_trait = - self.return_position_impl_trait_from_match_expectation(orig_expected); + self.return_position_impl_trait_from_match_expectation(orig_expected, expr.span); let (arm_block_id, arm_span) = if let hir::ExprKind::Block(blk, _) = arm.body.kind { (Some(blk.hir_id), self.find_block_span(blk)) @@ -586,8 +586,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { pub(crate) fn return_position_impl_trait_from_match_expectation( &self, expectation: Expectation<'tcx>, + span: Span, ) -> Option { - let expected_ty = expectation.to_option(self)?; + let expected_ty = expectation.structurally_resolve(self, span)?; let (def_id, args) = match *expected_ty.kind() { // FIXME: Could also check that the RPIT is not defined ty::Alias(ty::Opaque, alias_ty) => (alias_ty.def_id.as_local()?, alias_ty.args), diff --git a/compiler/rustc_hir_typeck/src/callee.rs b/compiler/rustc_hir_typeck/src/callee.rs index a92482e6a0e39..7994f7516949f 100644 --- a/compiler/rustc_hir_typeck/src/callee.rs +++ b/compiler/rustc_hir_typeck/src/callee.rs @@ -573,7 +573,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { // We didn't record the in scope traits during late resolution // so we need to probe AllTraits unfortunately ProbeScope::AllTraits, - expected.only_has_type(self), + expected.structurally_resolve_hard_expectation(self, call_expr.span), ) else { return; }; diff --git a/compiler/rustc_hir_typeck/src/closure.rs b/compiler/rustc_hir_typeck/src/closure.rs index e715a7f7e1588..ac8405486b6c5 100644 --- a/compiler/rustc_hir_typeck/src/closure.rs +++ b/compiler/rustc_hir_typeck/src/closure.rs @@ -57,11 +57,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { // It's always helpful for inference if we know the kind of // closure sooner rather than later, so first examine the expected // type, and see if can glean a closure kind from there. - let (expected_sig, expected_kind) = match expected.to_option(self) { - Some(ty) => self.deduce_closure_signature( - self.try_structurally_resolve_type(expr_span, ty), - closure.kind, - ), + let (expected_sig, expected_kind) = match expected.structurally_resolve(self, expr_span) { + Some(ty) => self.deduce_closure_signature(ty, closure.kind), None => (None, None), }; diff --git a/compiler/rustc_hir_typeck/src/expectation.rs b/compiler/rustc_hir_typeck/src/expectation.rs index 4653458b5ddcc..91a75d0e4486a 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 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), @@ -77,22 +81,16 @@ impl<'a, 'tcx> Expectation<'tcx> { } } - /// Resolves `expected` by a single level if it is a variable. If - /// there is no expected type or resolution is not possible (e.g., - /// no constraints yet present), just returns `self`. - fn resolve(self, fcx: &FnCtxt<'a, 'tcx>) -> Expectation<'tcx> { + pub(super) fn structurally_resolve( + self, + fcx: &FnCtxt<'a, 'tcx>, + span: Span, + ) -> Option> { match self { - NoExpectation => NoExpectation, - ExpectCastableToType(t) => ExpectCastableToType(fcx.resolve_vars_if_possible(t)), - ExpectHasType(t) => ExpectHasType(fcx.resolve_vars_if_possible(t)), - ExpectRvalueLikeUnsized(t) => ExpectRvalueLikeUnsized(fcx.resolve_vars_if_possible(t)), - } - } - - pub(super) fn to_option(self, fcx: &FnCtxt<'a, 'tcx>) -> Option> { - match self.resolve(fcx) { NoExpectation => None, - ExpectCastableToType(ty) | ExpectHasType(ty) | ExpectRvalueLikeUnsized(ty) => Some(ty), + ExpectCastableToType(ty) | ExpectHasType(ty) | ExpectRvalueLikeUnsized(ty) => { + Some(fcx.try_structurally_resolve_type(span, ty)) + } } } @@ -100,16 +98,14 @@ impl<'a, 'tcx> Expectation<'tcx> { /// a **hard constraint** (i.e., something that must be satisfied /// for the program to type-check). `only_has_type` will return /// such a constraint, if it exists. - pub(super) fn only_has_type(self, fcx: &FnCtxt<'a, 'tcx>) -> Option> { + pub(super) fn structurally_resolve_hard_expectation( + self, + fcx: &FnCtxt<'a, 'tcx>, + span: Span, + ) -> Option> { match self { - ExpectHasType(ty) => Some(fcx.resolve_vars_if_possible(ty)), + ExpectHasType(ty) => Some(fcx.try_structurally_resolve_type(span, ty)), NoExpectation | ExpectCastableToType(_) | ExpectRvalueLikeUnsized(_) => None, } } - - /// Like `only_has_type`, but instead of returning `None` if no - /// hard constraint exists, creates a fresh type variable. - pub(super) fn coercion_target_type(self, fcx: &FnCtxt<'a, 'tcx>, span: Span) -> Ty<'tcx> { - self.only_has_type(fcx).unwrap_or_else(|| fcx.next_ty_var(span)) - } } diff --git a/compiler/rustc_hir_typeck/src/expr.rs b/compiler/rustc_hir_typeck/src/expr.rs index b4715839cf56e..288fa2533aa02 100644 --- a/compiler/rustc_hir_typeck/src/expr.rs +++ b/compiler/rustc_hir_typeck/src/expr.rs @@ -628,21 +628,24 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { expected: Expectation<'tcx>, expr: &'tcx hir::Expr<'tcx>, ) -> Ty<'tcx> { - let hint = expected.only_has_type(self).map_or(NoExpectation, |ty| { - match ty.kind() { - ty::Ref(_, ty, _) | ty::RawPtr(ty, _) => { - if oprnd.is_syntactic_place_expr() { - // Places may legitimately have unsized types. - // For example, dereferences of a wide pointer and - // the last field of a struct can be unsized. - ExpectHasType(*ty) - } else { - Expectation::rvalue_hint(self, *ty) + let hint = expected.structurally_resolve_hard_expectation(self, expr.span).map_or( + NoExpectation, + |ty| { + match ty.kind() { + ty::Ref(_, ty, _) | ty::RawPtr(ty, _) => { + if oprnd.is_syntactic_place_expr() { + // Places may legitimately have unsized types. + // For example, dereferences of a wide pointer and + // the last field of a struct can be unsized. + ExpectHasType(*ty) + } else { + Expectation::rvalue_hint(self, *ty) + } } + _ => NoExpectation, } - _ => NoExpectation, - } - }); + }, + ); let ty = self.check_expr_with_expectation_and_needs(oprnd, hint, Needs::maybe_mut_place(mutbl)); @@ -1294,7 +1297,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.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); @@ -1305,7 +1308,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { // `expected` if it represents a *hard* constraint // (`only_has_type`); otherwise, we just go with a // fresh type variable. - let coerce_to_ty = expected.coercion_target_type(self, sp); + let coerce_to_ty = expected + .structurally_resolve_hard_expectation(self, sp) + .unwrap_or_else(|| self.next_ty_var(sp)); let mut coerce: DynamicCoerceMany<'_> = CoerceMany::new(coerce_to_ty); coerce.coerce(self, &self.misc(sp), then_expr, then_ty); @@ -1315,7 +1320,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { let else_diverges = self.diverges.get(); let tail_defines_return_position_impl_trait = - self.return_position_impl_trait_from_match_expectation(orig_expected); + self.return_position_impl_trait_from_match_expectation(orig_expected, sp); let if_cause = self.if_cause( sp, cond_expr.span, @@ -1355,8 +1360,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.structurally_resolve_hard_expectation(self, expr.span); + 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); } @@ -1522,7 +1527,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { let coerce = match source { // you can only use break with a value from a normal `loop { }` hir::LoopSource::Loop => { - let coerce_to = expected.coercion_target_type(self, body.span); + let coerce_to = expected + .structurally_resolve_hard_expectation(self, body.span) + .unwrap_or_else(|| self.next_ty_var(body.span)); Some(CoerceMany::new(coerce_to)) } @@ -1639,7 +1646,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { ) -> Ty<'tcx> { let element_ty = if !args.is_empty() { let coerce_to = expected - .to_option(self) + .structurally_resolve(self, expr.span) .and_then(|uty| match *uty.kind() { ty::Array(ty, _) | ty::Slice(ty) => Some(ty), _ => None, @@ -1824,13 +1831,13 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { expected: Expectation<'tcx>, expr: &'tcx hir::Expr<'tcx>, ) -> Ty<'tcx> { - let flds = expected.only_has_type(self).and_then(|ty| { - let ty = self.try_structurally_resolve_type(expr.span, ty); - match ty.kind() { + let flds = + expected.structurally_resolve_hard_expectation(self, expr.span).and_then(|ty| match ty + .kind() + { ty::Tuple(flds) => Some(&flds[..]), _ => None, - } - }); + }); let elt_ts_iter = elts.iter().enumerate().map(|(i, e)| match flds { Some(fs) if i < fs.len() => { @@ -1904,17 +1911,18 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { let tcx = self.tcx; 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); - ocx.sup(&self.misc(span), self.param_env, expected, adt_ty)?; - if !ocx.select_where_possible().is_empty() { - return Err(TypeError::Mismatch); - } - Ok(self.resolve_vars_if_possible(adt_ty)) - }) - .ok() - }); + let adt_ty_hint = + expected.structurally_resolve_hard_expectation(self, expr.span).and_then(|expected| { + self.fudge_inference_if_ok(|| { + let ocx = ObligationCtxt::new(self); + ocx.sup(&self.misc(span), self.param_env, expected, adt_ty)?; + if !ocx.select_where_possible().is_empty() { + return Err(TypeError::Mismatch); + } + Ok(self.resolve_vars_if_possible(adt_ty)) + }) + .ok() + }); if let Some(adt_ty_hint) = adt_ty_hint { // re-link the variables that the fudging above can create. self.demand_eqtype(span, adt_ty_hint, adt_ty); @@ -2682,7 +2690,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { base_ty, field, did, - expected.only_has_type(self), + expected.structurally_resolve_hard_expectation(self, expr.span), ); return Ty::new_error(self.tcx(), guar); } @@ -2693,7 +2701,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { field, base_ty, expr.hir_id, - expected.only_has_type(self), + expected.structurally_resolve_hard_expectation(self, expr.span), ) { self.ban_take_value_of_method(expr, base_ty, field) } else if !base_ty.is_primitive_ty() { diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs index 63777f82f1ae3..8880b1ec16e31 100644 --- a/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs +++ b/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs @@ -218,7 +218,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { // is because the inference guidance here is only speculative. let formal_output = self.resolve_vars_with_obligations(formal_output); let expected_input_tys: Option> = expectation - .only_has_type(self) + .structurally_resolve_hard_expectation(self, call_span) .and_then(|expected_output| { self.fudge_inference_if_ok(|| { let ocx = ObligationCtxt::new(self); @@ -302,7 +302,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { // We introduce a helper function to demand that a given argument satisfy a given input // This is more complicated than just checking type equality, as arguments could be coerced // This version writes those types back so further type checking uses the narrowed types - let demand_compatible = |idx| { + let demand_compatible = |idx: usize| { let formal_input_ty: Ty<'tcx> = formal_input_tys[idx]; let expected_input_ty: Ty<'tcx> = expected_input_tys[idx]; let provided_arg = &provided_args[idx]; @@ -319,7 +319,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { // 2. Coerce to the most detailed type that could be coerced // to, which is `expected_ty` if `rvalue_hint` returns an // `ExpectHasType(expected_ty)`, or the `formal_ty` otherwise. - let coerced_ty = expectation.only_has_type(self).unwrap_or(formal_input_ty); + let coerced_ty = expectation + .structurally_resolve_hard_expectation(self, provided_args[idx].span) + .unwrap_or(formal_input_ty); // Cause selection errors caused by resolving a single argument to point at the // argument and not the call. This lets us customize the span pointed to in the @@ -731,7 +733,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { let (arg_ty, arg_span) = provided_arg_tys[provided_idx]; let expectation = Expectation::rvalue_hint(self, expected_input_ty); - let coerced_ty = expectation.only_has_type(self).unwrap_or(formal_input_ty); + let coerced_ty = expectation + .structurally_resolve_hard_expectation(self, arg_span) + .unwrap_or(formal_input_ty); let can_coerce = self.may_coerce(arg_ty, coerced_ty); if !can_coerce { return Compatibility::Incompatible(Some(ty::error::TypeError::Sorts( @@ -945,21 +949,20 @@ 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) + .structurally_resolve_hard_expectation(self, provided_args[provided_idx].span) .unwrap_or(formal_ty), None, None, @@ -991,7 +994,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, ); @@ -1001,7 +1004,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { call_ident, expected_ty, provided_ty, - provided_args[*provided_idx], + provided_args[provided_idx], is_method, ); @@ -1138,7 +1141,10 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { provided_args[provided_idx], provided_ty, Expectation::rvalue_hint(self, expected_ty) - .only_has_type(self) + .structurally_resolve_hard_expectation( + self, + provided_args[provided_idx].span, + ) .unwrap_or(formal_ty), None, None, @@ -1594,23 +1600,25 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { ast::LitKind::Int(_, ast::LitIntType::Signed(t)) => Ty::new_int(tcx, ty::int_ty(t)), ast::LitKind::Int(_, ast::LitIntType::Unsigned(t)) => Ty::new_uint(tcx, ty::uint_ty(t)), ast::LitKind::Int(_, ast::LitIntType::Unsuffixed) => { - let opt_ty = expected.to_option(self).and_then(|ty| match ty.kind() { - ty::Int(_) | ty::Uint(_) => Some(ty), - ty::Char => Some(tcx.types.u8), - ty::RawPtr(..) => Some(tcx.types.usize), - ty::FnDef(..) | ty::FnPtr(..) => Some(tcx.types.usize), - _ => None, - }); + let opt_ty = + expected.structurally_resolve(self, lit.span).and_then(|ty| match ty.kind() { + ty::Int(_) | ty::Uint(_) => Some(ty), + ty::Char => Some(tcx.types.u8), + ty::RawPtr(..) => Some(tcx.types.usize), + ty::FnDef(..) | ty::FnPtr(..) => Some(tcx.types.usize), + _ => None, + }); opt_ty.unwrap_or_else(|| self.next_int_var()) } ast::LitKind::Float(_, ast::LitFloatType::Suffixed(t)) => { Ty::new_float(tcx, ty::float_ty(t)) } ast::LitKind::Float(_, ast::LitFloatType::Unsuffixed) => { - let opt_ty = expected.to_option(self).and_then(|ty| match ty.kind() { - ty::Float(_) => Some(ty), - _ => None, - }); + let opt_ty = + expected.structurally_resolve(self, lit.span).and_then(|ty| match ty.kind() { + ty::Float(_) => Some(ty), + _ => None, + }); opt_ty.unwrap_or_else(|| self.next_float_var()) } ast::LitKind::Bool(_) => tcx.types.bool, @@ -1845,7 +1853,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { // case we can ignore the tail expression (e.g., `'a: { // break 'a 22; }` would not force the type of the block // to be `()`). - let coerce_to_ty = expected.coercion_target_type(self, blk.span); + let coerce_to_ty = expected + .structurally_resolve_hard_expectation(self, blk.span) + .unwrap_or_else(|| self.next_ty_var(blk.span)); let coerce = if blk.targeted_by_break { CoerceMany::new(coerce_to_ty) } else { @@ -1925,7 +1935,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { self, &self.misc(sp), |err| { - if let Some(expected_ty) = expected.only_has_type(self) { + if let Some(expected_ty) = + expected.structurally_resolve_hard_expectation(self, blk.span) + { if blk.stmts.is_empty() && blk.expr.is_none() { self.suggest_boxing_when_appropriate( err, diff --git a/compiler/rustc_hir_typeck/src/method/suggest.rs b/compiler/rustc_hir_typeck/src/method/suggest.rs index cff2aa6899390..b00c563ce7bdc 100644 --- a/compiler/rustc_hir_typeck/src/method/suggest.rs +++ b/compiler/rustc_hir_typeck/src/method/suggest.rs @@ -732,7 +732,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { rcvr_ty, cal, span, - expected.only_has_type(self), + expected.structurally_resolve_hard_expectation(self, span), ); } if let Some(span) = @@ -802,14 +802,14 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { output_ty, call_expr, ProbeScope::AllTraits, - expected.only_has_type(self), + expected.structurally_resolve_hard_expectation(self, span), ); probe.is_ok() }); self.note_internal_mutation_in_method( &mut err, rcvr_expr, - expected.to_option(self), + expected.structurally_resolve(self, span), rcvr_ty, ); } @@ -1499,7 +1499,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { span, rcvr_ty, item_name, - expected.only_has_type(self), + expected.structurally_resolve_hard_expectation(self, span), ); } @@ -1552,7 +1552,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { no_match_data.out_of_scope_traits.clone(), static_candidates, unsatisfied_bounds, - expected.only_has_type(self), + expected.structurally_resolve_hard_expectation(self, span), trait_missing_method, ); } @@ -3161,7 +3161,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { if let Ok(pick) = self.probe_for_name( Mode::Path, item_name, - expected.only_has_type(self), + // FIXME(-Znext-solver): Span is scuffed. + expected.structurally_resolve_hard_expectation(self, item_name.span), IsSuggestion(true), deref_ty, ty.hir_id, diff --git a/compiler/rustc_hir_typeck/src/op.rs b/compiler/rustc_hir_typeck/src/op.rs index 72b930ee84df6..3a7909cde0e33 100644 --- a/compiler/rustc_hir_typeck/src/op.rs +++ b/compiler/rustc_hir_typeck/src/op.rs @@ -907,7 +907,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { rhs_hir_id: opt_rhs_expr.map(|expr| expr.hir_id), rhs_span: opt_rhs_expr.map(|expr| expr.span), rhs_is_lit: opt_rhs_expr.is_some_and(|expr| matches!(expr.kind, hir::ExprKind::Lit(_))), - output_ty: expected.only_has_type(self), + output_ty: expected.structurally_resolve_hard_expectation(self, span), }); let method = diff --git a/tests/ui/generic-associated-types/ambig-hr-projection-issue-93340.next.stderr b/tests/ui/generic-associated-types/ambig-hr-projection-issue-93340.next.stderr index d624fb1e42b6f..4cc0242f01675 100644 --- a/tests/ui/generic-associated-types/ambig-hr-projection-issue-93340.next.stderr +++ b/tests/ui/generic-associated-types/ambig-hr-projection-issue-93340.next.stderr @@ -1,19 +1,14 @@ -error[E0283]: type annotations needed - --> $DIR/ambig-hr-projection-issue-93340.rs:17:5 +error[E0284]: type annotations needed: cannot satisfy `impl for<'a, 'b> Fn(::RefType<'a>, ::RefType<'b>) -> O == for<'a, 'b> fn(<_ as Scalar>::RefType<'a>, <_ as Scalar>::RefType<'b>) -> O {cmp_eq::<_, _, O>}` + --> $DIR/ambig-hr-projection-issue-93340.rs:15:51 | -LL | cmp_eq - | ^^^^^^ cannot infer type of the type parameter `A` declared on the function `cmp_eq` - | - = note: cannot satisfy `_: Scalar` -note: required by a bound in `cmp_eq` - --> $DIR/ambig-hr-projection-issue-93340.rs:10:22 - | -LL | fn cmp_eq<'a, 'b, A: Scalar, B: Scalar, O: Scalar>(a: A::RefType<'a>, b: B::RefType<'b>) -> O { - | ^^^^^^ required by this bound in `cmp_eq` -help: consider specifying the generic arguments - | -LL | cmp_eq:: - | +++++++++++ +LL | ) -> impl Fn(A::RefType<'_>, B::RefType<'_>) -> O { + | ___________________________________________________^ +LL | | +LL | | +LL | | cmp_eq +LL | | +LL | | } + | |_^ cannot satisfy `impl for<'a, 'b> Fn(::RefType<'a>, ::RefType<'b>) -> O == for<'a, 'b> fn(<_ as Scalar>::RefType<'a>, <_ as Scalar>::RefType<'b>) -> O {cmp_eq::<_, _, O>}` error[E0277]: expected a `Fn(::RefType<'_>, ::RefType<'_>)` closure, found `for<'a, 'b> fn(::RefType<'a>, <_ as Scalar>::RefType<'b>) -> O {cmp_eq::}` --> $DIR/ambig-hr-projection-issue-93340.rs:14:1 @@ -26,5 +21,5 @@ LL | | ) -> impl Fn(A::RefType<'_>, B::RefType<'_>) -> O { error: aborting due to 2 previous errors -Some errors have detailed explanations: E0277, E0283. +Some errors have detailed explanations: E0277, E0284. For more information about an error, try `rustc --explain E0277`. diff --git a/tests/ui/generic-associated-types/ambig-hr-projection-issue-93340.old.stderr b/tests/ui/generic-associated-types/ambig-hr-projection-issue-93340.old.stderr index 4a293d44e0e3d..2beb76cc93b35 100644 --- a/tests/ui/generic-associated-types/ambig-hr-projection-issue-93340.old.stderr +++ b/tests/ui/generic-associated-types/ambig-hr-projection-issue-93340.old.stderr @@ -1,5 +1,5 @@ error[E0283]: type annotations needed - --> $DIR/ambig-hr-projection-issue-93340.rs:17:5 + --> $DIR/ambig-hr-projection-issue-93340.rs:18:5 | LL | cmp_eq | ^^^^^^ cannot infer type of the type parameter `A` declared on the function `cmp_eq` diff --git a/tests/ui/generic-associated-types/ambig-hr-projection-issue-93340.rs b/tests/ui/generic-associated-types/ambig-hr-projection-issue-93340.rs index 5f2e134109e22..622e23b97baac 100644 --- a/tests/ui/generic-associated-types/ambig-hr-projection-issue-93340.rs +++ b/tests/ui/generic-associated-types/ambig-hr-projection-issue-93340.rs @@ -13,9 +13,10 @@ fn cmp_eq<'a, 'b, A: Scalar, B: Scalar, O: Scalar>(a: A::RefType<'a>, b: B::RefT fn build_expression( ) -> impl Fn(A::RefType<'_>, B::RefType<'_>) -> O { - //[next]~^^ expected a `Fn(::RefType<'_>, ::RefType<'_>)` closure + //[next]~^^ expected a + //[next]~^^ type annotations needed cmp_eq - //~^ ERROR type annotations needed + //[old]~^ ERROR type annotations needed } fn main() {} 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 5caf0eb2fd4e3..0be710c1c4d3f 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,14 @@ -error[E0283]: type annotations needed - --> $DIR/auto-trait-selection-freeze.rs:19:16 - | -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, U: Default>(_: T) -> U { - | ^^^^^^^^ required by this bound in `is_trait` -help: consider specifying the generic arguments - | -LL | if false { is_trait::(foo()) } else { Default::default() } - | ++++++++ +error[E0284]: type annotations needed: cannot satisfy `impl Sized == _` + --> $DIR/auto-trait-selection-freeze.rs:18:24 + | +LL | fn foo() -> impl Sized { + | ________________________^ +LL | | +LL | | if false { is_trait(foo()) } else { Default::default() } +LL | | +LL | | } + | |_^ 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-freeze.old.stderr b/tests/ui/impl-trait/auto-trait-selection-freeze.old.stderr index b4d2229d408d2..606b58a7d6802 100644 --- a/tests/ui/impl-trait/auto-trait-selection-freeze.old.stderr +++ b/tests/ui/impl-trait/auto-trait-selection-freeze.old.stderr @@ -1,5 +1,5 @@ error[E0283]: type annotations needed - --> $DIR/auto-trait-selection-freeze.rs:19:16 + --> $DIR/auto-trait-selection-freeze.rs:20:16 | LL | if false { is_trait(foo()) } else { Default::default() } | ^^^^^^^^ cannot infer type of the type parameter `U` declared on the function `is_trait` diff --git a/tests/ui/impl-trait/auto-trait-selection-freeze.rs b/tests/ui/impl-trait/auto-trait-selection-freeze.rs index 7306a1c41f746..17786108d0fc6 100644 --- a/tests/ui/impl-trait/auto-trait-selection-freeze.rs +++ b/tests/ui/impl-trait/auto-trait-selection-freeze.rs @@ -16,8 +16,9 @@ trait Trait {} impl Trait for T {} impl Trait for T {} fn foo() -> impl Sized { + //[next]~^ ERROR type annotations needed if false { is_trait(foo()) } else { Default::default() } - //~^ ERROR: type annotations needed + //[old]~^ ERROR: type annotations needed } fn main() {} diff --git a/tests/ui/impl-trait/auto-trait-selection.next.stderr b/tests/ui/impl-trait/auto-trait-selection.next.stderr index d34fdcc44967f..ac8286dce3533 100644 --- a/tests/ui/impl-trait/auto-trait-selection.next.stderr +++ b/tests/ui/impl-trait/auto-trait-selection.next.stderr @@ -1,22 +1,14 @@ -error[E0283]: type annotations needed - --> $DIR/auto-trait-selection.rs:15:16 - | -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, U: Default>(_: T) -> U { - | ^^^^^^^^ required by this bound in `is_trait` -help: consider specifying the generic arguments - | -LL | if false { is_trait::(foo()) } else { Default::default() } - | ++++++++ +error[E0284]: type annotations needed: cannot satisfy `impl Sized == _` + --> $DIR/auto-trait-selection.rs:14:24 + | +LL | fn foo() -> impl Sized { + | ________________________^ +LL | | +LL | | if false { is_trait(foo()) } else { Default::default() } +LL | | +LL | | } + | |_^ 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.old.stderr b/tests/ui/impl-trait/auto-trait-selection.old.stderr index 1b5fd95fdf903..fd08f93580f92 100644 --- a/tests/ui/impl-trait/auto-trait-selection.old.stderr +++ b/tests/ui/impl-trait/auto-trait-selection.old.stderr @@ -1,5 +1,5 @@ error[E0283]: type annotations needed - --> $DIR/auto-trait-selection.rs:15:16 + --> $DIR/auto-trait-selection.rs:16:16 | LL | if false { is_trait(foo()) } else { Default::default() } | ^^^^^^^^ cannot infer type of the type parameter `U` declared on the function `is_trait` diff --git a/tests/ui/impl-trait/auto-trait-selection.rs b/tests/ui/impl-trait/auto-trait-selection.rs index ee5612459c257..8019c85c90c65 100644 --- a/tests/ui/impl-trait/auto-trait-selection.rs +++ b/tests/ui/impl-trait/auto-trait-selection.rs @@ -12,8 +12,9 @@ trait Trait {} impl Trait for T {} impl Trait for T {} fn foo() -> impl Sized { + //[next]~^ ERROR: type annotations needed if false { is_trait(foo()) } else { Default::default() } - //~^ ERROR: type annotations needed + //[old]~^ ERROR: type annotations needed } fn main() {} diff --git a/tests/ui/overloaded/overloaded-calls-nontuple.stderr b/tests/ui/overloaded/overloaded-calls-nontuple.stderr index 22598f3a39010..c17a49e5f8bcb 100644 --- a/tests/ui/overloaded/overloaded-calls-nontuple.stderr +++ b/tests/ui/overloaded/overloaded-calls-nontuple.stderr @@ -43,17 +43,17 @@ help: use a unary tuple instead LL | self.call_mut((z,)) | + ++ -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 diff --git a/tests/ui/traits/negative-bounds/opaque-type-unsatisfied-bound.stderr b/tests/ui/traits/negative-bounds/opaque-type-unsatisfied-bound.stderr index 3dad6d534fd83..439b7ae2514c6 100644 --- a/tests/ui/traits/negative-bounds/opaque-type-unsatisfied-bound.stderr +++ b/tests/ui/traits/negative-bounds/opaque-type-unsatisfied-bound.stderr @@ -3,18 +3,24 @@ error[E0277]: the trait bound `(): !Sized` is not satisfied | LL | fn weird0() -> impl Sized + !Sized {} | ^^^^^^^^^^^^^^^^^^^ the trait bound `(): !Sized` is not satisfied + | + = note: the return type of a function must have a statically known size error[E0277]: the trait bound `(): !Sized` is not satisfied --> $DIR/opaque-type-unsatisfied-bound.rs:17:16 | LL | fn weird1() -> impl !Sized + Sized {} | ^^^^^^^^^^^^^^^^^^^ the trait bound `(): !Sized` is not satisfied + | + = note: the return type of a function must have a statically known size error[E0277]: the trait bound `(): !Sized` is not satisfied --> $DIR/opaque-type-unsatisfied-bound.rs:19:16 | LL | fn weird2() -> impl !Sized {} | ^^^^^^^^^^^ the trait bound `(): !Sized` is not satisfied + | + = note: the return type of a function must have a statically known size error[E0277]: the trait bound `impl !Trait: Trait` is not satisfied --> $DIR/opaque-type-unsatisfied-bound.rs:12:13 diff --git a/tests/ui/traits/negative-bounds/opaque-type-unsatisfied-fn-bound.stderr b/tests/ui/traits/negative-bounds/opaque-type-unsatisfied-fn-bound.stderr index 760e5aa62f2c1..676f00e95da75 100644 --- a/tests/ui/traits/negative-bounds/opaque-type-unsatisfied-fn-bound.stderr +++ b/tests/ui/traits/negative-bounds/opaque-type-unsatisfied-fn-bound.stderr @@ -3,6 +3,8 @@ error[E0277]: the trait bound `(): !Fn(u32)` is not satisfied | LL | fn produce() -> impl !Fn<(u32,)> {} | ^^^^^^^^^^^^^^^^ the trait bound `(): !Fn(u32)` is not satisfied + | + = note: the return type of a function must have a statically known size error: aborting due to 1 previous error 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 0000000000000..d6b3816b9eb12 --- /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 Mirror for T { + type Assoc = T; +} + +fn id(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; 2] as Mirror>::Assoc>([Box::new(1i32), Box::new(1u32)]); + + // Make sure we resolve expected element of tuple. + id::<<(Box,) 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 0000000000000..d406f3949a28a --- /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() {} diff --git a/tests/ui/type-alias-impl-trait/nested-tait-inference2.current.stderr b/tests/ui/type-alias-impl-trait/nested-tait-inference2.current.stderr index 9da3926ac7081..23626814bb554 100644 --- a/tests/ui/type-alias-impl-trait/nested-tait-inference2.current.stderr +++ b/tests/ui/type-alias-impl-trait/nested-tait-inference2.current.stderr @@ -3,7 +3,7 @@ error[E0277]: the trait bound `(): Foo` is not satisfied | LL | fn foo() -> impl Foo { | ^^^^^^^^^^^^^^ the trait `Foo` is not implemented for `()` -LL | +... LL | () | -- return type was inferred to be `()` here | diff --git a/tests/ui/type-alias-impl-trait/nested-tait-inference2.next.stderr b/tests/ui/type-alias-impl-trait/nested-tait-inference2.next.stderr index 9647d9e376eb4..94b5b950178dd 100644 --- a/tests/ui/type-alias-impl-trait/nested-tait-inference2.next.stderr +++ b/tests/ui/type-alias-impl-trait/nested-tait-inference2.next.stderr @@ -1,8 +1,13 @@ error[E0284]: type annotations needed: cannot satisfy `impl Foo == ()` - --> $DIR/nested-tait-inference2.rs:19:5 + --> $DIR/nested-tait-inference2.rs:17:28 | -LL | () - | ^^ cannot satisfy `impl Foo == ()` +LL | fn foo() -> impl Foo { + | ____________________________^ +LL | | +LL | | +LL | | () +LL | | } + | |_^ cannot satisfy `impl Foo == ()` error: aborting due to 1 previous error diff --git a/tests/ui/type-alias-impl-trait/nested-tait-inference2.rs b/tests/ui/type-alias-impl-trait/nested-tait-inference2.rs index 28d72b0cbeede..b673416659d77 100644 --- a/tests/ui/type-alias-impl-trait/nested-tait-inference2.rs +++ b/tests/ui/type-alias-impl-trait/nested-tait-inference2.rs @@ -15,9 +15,9 @@ impl Foo<()> for () {} impl Foo for () {} fn foo() -> impl Foo { - //[current]~^ ERROR: the trait bound `(): Foo` is not satisfied - () //[next]~^ ERROR: cannot satisfy `impl Foo == ()` + //[current]~^^ ERROR: the trait bound `(): Foo` is not satisfied + () } fn main() {}