diff --git a/compiler/rustc_infer/src/infer/at.rs b/compiler/rustc_infer/src/infer/at.rs index ce2698ef44cd4..c02ef5517262b 100644 --- a/compiler/rustc_infer/src/infer/at.rs +++ b/compiler/rustc_infer/src/infer/at.rs @@ -368,6 +368,29 @@ impl<'tcx> ToTrace<'tcx> for Const<'tcx> { } } +impl<'tcx> ToTrace<'tcx> for GenericArg<'tcx> { + fn to_trace( + tcx: TyCtxt<'tcx>, + cause: &ObligationCause<'tcx>, + a_is_expected: bool, + a: Self, + b: Self, + ) -> TypeTrace<'tcx> { + match (a.unpack(), b.unpack()) { + (GenericArgKind::Type(a), GenericArgKind::Type(b)) => { + <_>::to_trace(tcx, cause, a_is_expected, a, b) + } + (GenericArgKind::Lifetime(a), GenericArgKind::Lifetime(b)) => { + <_>::to_trace(tcx, cause, a_is_expected, a, b) + } + (GenericArgKind::Const(a), GenericArgKind::Const(b)) => { + <_>::to_trace(tcx, cause, a_is_expected, a, b) + } + _ => bug!("cannot trace GenericArgs of different kinds"), + } + } +} + impl<'tcx> ToTrace<'tcx> for ty::Term<'tcx> { fn to_trace( _: TyCtxt<'tcx>, diff --git a/compiler/rustc_typeck/src/check/expr.rs b/compiler/rustc_typeck/src/check/expr.rs index b4476d5c59b2b..25b7fb3dab3dc 100644 --- a/compiler/rustc_typeck/src/check/expr.rs +++ b/compiler/rustc_typeck/src/check/expr.rs @@ -1592,7 +1592,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { if let Some(base_expr) = base_expr { // FIXME: We are currently creating two branches here in order to maintain // consistency. But they should be merged as much as possible. - let fru_tys = if self.tcx.features().type_changing_struct_update { + let fru_tys = if self.tcx.features().type_changing_struct_update || true { if adt.is_struct() { // Make some fresh substitutions for our ADT type. let fresh_substs = self.fresh_substs_for_item(base_expr.span, adt.did()); @@ -1656,6 +1656,25 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { self.resolve_vars_if_possible(fresh_base_ty), |_| {}, ); + // ... + let variances = tcx.variances_of(adt.did()); + let constrained_substs = self.resolve_vars_with_obligations(fresh_substs); + for i in 0..substs.len() { + if constrained_substs[i] == fresh_substs[i] { + match self.at(&self.misc(base_expr.span), self.param_env).relate( + substs[i], + variances[i], + constrained_substs[i], + ) { + Ok(InferOk { obligations, value: () }) => { + self.register_predicates(obligations) + } + Err(_) => { + bug!(); + } + } + } + } fru_tys } else { // Check the base_expr, regardless of a bad expected adt_ty, so we can get diff --git a/compiler/rustc_typeck/src/check/fn_ctxt/_impl.rs b/compiler/rustc_typeck/src/check/fn_ctxt/_impl.rs index ea7ebdf91d012..481a576f0e134 100644 --- a/compiler/rustc_typeck/src/check/fn_ctxt/_impl.rs +++ b/compiler/rustc_typeck/src/check/fn_ctxt/_impl.rs @@ -80,27 +80,29 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { /// version (resolve_vars_if_possible), this version will /// also select obligations if it seems useful, in an effort /// to get more type information. - pub(in super::super) fn resolve_vars_with_obligations(&self, ty: Ty<'tcx>) -> Ty<'tcx> { - self.resolve_vars_with_obligations_and_mutate_fulfillment(ty, |_| {}) + pub(in super::super) fn resolve_vars_with_obligations>(&self, t: T) -> T { + self.resolve_vars_with_obligations_and_mutate_fulfillment(t, |_| {}) } #[instrument(skip(self, mutate_fulfillment_errors), level = "debug")] - pub(in super::super) fn resolve_vars_with_obligations_and_mutate_fulfillment( + pub(in super::super) fn resolve_vars_with_obligations_and_mutate_fulfillment< + T: TypeFoldable<'tcx>, + >( &self, - mut ty: Ty<'tcx>, + mut t: T, mutate_fulfillment_errors: impl Fn(&mut Vec>), - ) -> Ty<'tcx> { + ) -> T { // No Infer()? Nothing needs doing. - if !ty.has_infer_types_or_consts() { + if !t.has_infer_types_or_consts() { debug!("no inference var, nothing needs doing"); - return ty; + return t; } // If `ty` is a type variable, see whether we already know what it is. - ty = self.resolve_vars_if_possible(ty); - if !ty.has_infer_types_or_consts() { - debug!(?ty); - return ty; + t = self.resolve_vars_if_possible(t); + if !t.has_infer_types_or_consts() { + debug!(?t); + return t; } // If not, try resolving pending obligations as much as @@ -108,10 +110,10 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { // indirect dependencies that don't seem worth tracking // precisely. self.select_obligations_where_possible(false, mutate_fulfillment_errors); - ty = self.resolve_vars_if_possible(ty); + t = self.resolve_vars_if_possible(t); - debug!(?ty); - ty + debug!(?t); + t } pub(in super::super) fn record_deferred_call_resolution(