Skip to content
Draft
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
70 changes: 3 additions & 67 deletions compiler/rustc_borrowck/src/type_check/canonical.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,9 +8,7 @@ use rustc_middle::mir::{Body, ConstraintCategory};
use rustc_middle::ty::{self, Ty, TyCtxt, TypeFoldable, Unnormalized, Upcast};
use rustc_span::Span;
use rustc_span::def_id::DefId;
use rustc_trait_selection::solve::NoSolution;
use rustc_trait_selection::traits::ObligationCause;
use rustc_trait_selection::traits::query::type_op::custom::CustomTypeOp;
use rustc_trait_selection::traits::query::type_op::{self, TypeOpOutput};
use tracing::{debug, instrument};

Expand Down Expand Up @@ -242,71 +240,9 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
body.source.def_id().expect_local(),
);

if self.infcx.next_trait_solver() {
let param_env = self.infcx.param_env;
// FIXME: Make this into a real type op?
self.fully_perform_op(
location.to_locations(),
ConstraintCategory::Boring,
CustomTypeOp::new(
|ocx| {
let structurally_normalize = |ty| {
ocx.structurally_normalize_ty(&cause, param_env, Unnormalized::new_wip(ty))
.unwrap_or_else(|_| bug!("struct tail should have been computable, since we computed it in HIR"))
};

let tail = tcx.struct_tail_raw(
ty,
&cause,
structurally_normalize,
|| {},
);

Ok(tail)
},
"normalizing struct tail",
),
)
.unwrap_or_else(|guar| Ty::new_error(tcx, guar))
} else {
let mut normalize = |ty| self.normalize(ty, location);
let tail = tcx.struct_tail_raw(ty, &cause, &mut normalize, || {});
normalize(tail)
}
}

#[instrument(skip(self), level = "debug")]
pub(super) fn structurally_resolve(
&mut self,
ty: Ty<'tcx>,
location: impl NormalizeLocation,
) -> Ty<'tcx> {
if self.infcx.next_trait_solver() {
let body = self.body;
let param_env = self.infcx.param_env;
// FIXME: Make this into a real type op?
self.fully_perform_op(
location.to_locations(),
ConstraintCategory::Boring,
CustomTypeOp::new(
|ocx| {
ocx.structurally_normalize_ty(
&ObligationCause::misc(
location.to_locations().span(body),
body.source.def_id().expect_local(),
),
param_env,
Unnormalized::new_wip(ty),
)
.map_err(|_| NoSolution)
},
"normalizing struct tail",
),
)
.unwrap_or_else(|guar| Ty::new_error(self.tcx(), guar))
} else {
self.normalize(ty, location)
}
let mut normalize = |ty| self.normalize(ty, location);
let tail = tcx.struct_tail_raw(ty, &cause, &mut normalize, || {});
normalize(tail)
}

#[instrument(skip(self), level = "debug")]
Expand Down
2 changes: 1 addition & 1 deletion compiler/rustc_borrowck/src/type_check/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -461,7 +461,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
let projected_ty = curr_projected_ty.projection_ty_core(
tcx,
proj,
|ty| self.structurally_resolve(ty, locations),
|ty| self.normalize(ty, locations),
|ty, variant_index, field, ()| PlaceTy::field_ty(tcx, ty, variant_index, field),
|_| unreachable!(),
);
Expand Down
31 changes: 8 additions & 23 deletions compiler/rustc_hir_analysis/src/autoderef.rs
Original file line number Diff line number Diff line change
Expand Up @@ -90,16 +90,9 @@ impl<'a, 'tcx> Iterator for Autoderef<'a, 'tcx> {
// NOTE: we may still need to normalize the built-in deref in case
// we have some type like `&<Ty as Trait>::Assoc`, since users of
// autoderef expect this type to have been structurally normalized.
if self.infcx.next_trait_solver()
&& let ty::Alias(..) = ty.kind()
{
let (normalized_ty, obligations) =
self.structurally_normalize_ty(Unnormalized::new_wip(ty))?;
self.state.obligations.extend(obligations);
(AutoderefKind::Builtin, normalized_ty)
} else {
(AutoderefKind::Builtin, ty)
}
let (normalized_ty, obligations) = self.normalize_ty(Unnormalized::new_wip(ty))?;
self.state.obligations.extend(obligations);
(AutoderefKind::Builtin, normalized_ty)
} else if let Some(ty) = self.overloaded_deref_ty(self.state.cur_ty) {
// The overloaded deref check already normalizes the pointee type.
(AutoderefKind::Overloaded, ty)
Expand Down Expand Up @@ -177,35 +170,27 @@ impl<'a, 'tcx> Autoderef<'a, 'tcx> {
return None;
}

let (normalized_ty, obligations) = self.structurally_normalize_ty(Unnormalized::new(
Ty::new_projection(tcx, trait_target_def_id, [ty]),
))?;
let (normalized_ty, obligations) = self
.normalize_ty(Unnormalized::new(Ty::new_projection(tcx, trait_target_def_id, [ty])))?;
debug!("overloaded_deref_ty({:?}) = ({:?}, {:?})", ty, normalized_ty, obligations);
self.state.obligations.extend(obligations);

Some(self.infcx.resolve_vars_if_possible(normalized_ty))
}

#[instrument(level = "debug", skip(self), ret)]
pub fn structurally_normalize_ty(
pub fn normalize_ty(
&self,
ty: Unnormalized<'tcx, Ty<'tcx>>,
) -> Option<(Ty<'tcx>, PredicateObligations<'tcx>)> {
let ocx = ObligationCtxt::new(self.infcx);
let Ok(normalized_ty) = ocx.structurally_normalize_ty(
let normalized_ty = ocx.normalize(
&traits::ObligationCause::misc(self.span, self.body_id),
self.param_env,
ty,
) else {
// We shouldn't have errors here in the old solver, except for
// evaluate/fulfill mismatches, but that's not a reason for an ICE.
return None;
};
);
let errors = ocx.try_evaluate_obligations();
if !errors.is_empty() {
if self.infcx.next_trait_solver() {
unreachable!();
}
// We shouldn't have errors here in the old solver, except for
// evaluate/fulfill mismatches, but that's not a reason for an ICE.
debug!(?errors, "encountered errors while fulfilling");
Expand Down
9 changes: 9 additions & 0 deletions compiler/rustc_hir_analysis/src/check/check.rs
Original file line number Diff line number Diff line change
Expand Up @@ -923,6 +923,15 @@ pub(crate) fn check_item_type(tcx: TyCtxt<'_>, def_id: LocalDefId) -> Result<(),
res = res.and(enter_wf_checking_ctxt(tcx, def_id, |wfcx| {
let ty = tcx.type_of(def_id).instantiate_identity();
let ty_span = tcx.ty_span(def_id);
// FIXME: Unnormalized version can ill-formed even if the normalized one is well-formed.
// Don't break the old solver for now. See `tests/ui/wf/wf-normalization-sized.rs`.
if tcx.next_trait_solver_globally() {
wfcx.register_wf_obligation(
ty_span,
Some(WellFormedLoc::Ty(def_id)),
ty.skip_normalization().into(),
);
}
let ty = wfcx.deeply_normalize(ty_span, Some(WellFormedLoc::Ty(def_id)), ty);
wfcx.register_wf_obligation(ty_span, Some(WellFormedLoc::Ty(def_id)), ty.into());
wfcx.register_bound(
Expand Down
11 changes: 0 additions & 11 deletions compiler/rustc_hir_analysis/src/coherence/orphan.rs
Original file line number Diff line number Diff line change
Expand Up @@ -315,17 +315,6 @@ fn orphan_check<'tcx>(
return Ok(user_ty);
}

let ty = if infcx.next_trait_solver() {
ocx.structurally_normalize_ty(
&cause,
ty::ParamEnv::empty(),
Unnormalized::new_wip(infcx.resolve_vars_if_possible(ty)),
)
.unwrap_or(ty)
} else {
ty
};

Ok::<_, !>(ty)
};

Expand Down
3 changes: 1 addition & 2 deletions compiler/rustc_hir_typeck/src/_match.rs
Original file line number Diff line number Diff line change
Expand Up @@ -60,8 +60,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
// type in that case)
let mut all_arms_diverge = Diverges::WarnedAlways;

let expected =
orig_expected.try_structurally_resolve_and_adjust_for_branches(self, expr.span);
let expected = orig_expected.try_structurally_resolve_and_adjust_for_branches(self);
debug!(?expected);

let mut coercion = {
Expand Down
5 changes: 2 additions & 3 deletions compiler/rustc_hir_typeck/src/callee.rs
Original file line number Diff line number Diff line change
Expand Up @@ -79,7 +79,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
_ => self.check_expr(callee_expr),
};

let expr_ty = self.try_structurally_resolve_type(call_expr.span, original_callee_ty);
let expr_ty = self.resolve_vars_with_obligations(original_callee_ty);

let mut autoderef = self.autoderef(callee_expr.span, expr_ty);
let mut result = None;
Expand Down Expand Up @@ -211,8 +211,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
arg_exprs: &'tcx [hir::Expr<'tcx>],
autoderef: &Autoderef<'a, 'tcx>,
) -> Option<CallStep<'tcx>> {
let adjusted_ty =
self.try_structurally_resolve_type(autoderef.span(), autoderef.final_ty());
let adjusted_ty = self.resolve_vars_with_obligations(autoderef.final_ty());

// If the callee is a function pointer or a closure, then we're all set.
match *adjusted_ty.kind() {
Expand Down
6 changes: 3 additions & 3 deletions compiler/rustc_hir_typeck/src/cast.rs
Original file line number Diff line number Diff line change
Expand Up @@ -102,7 +102,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
return Ok(Some(PointerKind::Thin));
}

let t = self.try_structurally_resolve_type(span, t);
let t = self.resolve_vars_with_obligations(t);

Ok(match *t.kind() {
ty::Slice(_) | ty::Str => Some(PointerKind::Length),
Expand Down Expand Up @@ -1041,8 +1041,8 @@ impl<'a, 'tcx> CastCheck<'tcx> {
mut m_cast: ty::TypeAndMut<'tcx>,
) -> Result<CastKind, CastError<'tcx>> {
// array-ptr-cast: allow mut-to-mut, mut-to-const, const-to-const
m_expr.ty = fcx.try_structurally_resolve_type(self.expr_span, m_expr.ty);
m_cast.ty = fcx.try_structurally_resolve_type(self.cast_span, m_cast.ty);
m_expr.ty = fcx.resolve_vars_with_obligations(m_expr.ty);
m_cast.ty = fcx.resolve_vars_with_obligations(m_cast.ty);

if m_expr.mutbl >= m_cast.mutbl
&& let ty::Array(ety, _) = m_expr.ty.kind()
Expand Down
9 changes: 4 additions & 5 deletions compiler/rustc_hir_typeck/src/closure.rs
Original file line number Diff line number Diff line change
Expand Up @@ -59,10 +59,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
// 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,
),
Some(ty) => {
self.deduce_closure_signature(self.resolve_vars_with_obligations(ty), closure.kind)
}
None => (None, None),
};

Expand Down Expand Up @@ -963,7 +962,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {

let closure_span = self.tcx.def_span(body_def_id);
let ret_ty = ret_coercion.borrow().expected_ty();
let ret_ty = self.try_structurally_resolve_type(closure_span, ret_ty);
let ret_ty = self.resolve_vars_with_obligations(ret_ty);

let get_future_output = |predicate: ty::Predicate<'tcx>, span| {
// Search for a pending obligation like
Expand Down
31 changes: 4 additions & 27 deletions compiler/rustc_hir_typeck/src/coercion.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1051,17 +1051,11 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
&self,
expr: &'tcx hir::Expr<'tcx>,
expr_ty: Ty<'tcx>,
mut target: Ty<'tcx>,
target: Ty<'tcx>,
allow_two_phase: AllowTwoPhase,
cause: Option<ObligationCause<'tcx>>,
) -> RelateResult<'tcx, Ty<'tcx>> {
let source = self.try_structurally_resolve_type(expr.span, expr_ty);
if self.next_trait_solver() {
target = self.try_structurally_resolve_type(
cause.as_ref().map_or(expr.span, |cause| cause.span),
target,
);
}
let source = self.resolve_vars_with_obligations(expr_ty);
debug!("coercion::try({:?}: {:?} -> {:?})", expr, source, target);

let cause =
Expand Down Expand Up @@ -1099,23 +1093,6 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
// Make sure to structurally resolve the types, since we use
// the `TyKind`s heavily in coercion.
let ocx = ObligationCtxt::new(self);
let structurally_resolve = |ty| {
let ty = self.shallow_resolve(ty);
if self.next_trait_solver()
&& let ty::Alias(..) = ty.kind()
{
ocx.structurally_normalize_ty(&cause, self.param_env, Unnormalized::new_wip(ty))
} else {
Ok(ty)
}
};
let Ok(expr_ty) = structurally_resolve(expr_ty) else {
return false;
};
let Ok(target_ty) = structurally_resolve(target_ty) else {
return false;
};

let Ok(ok) = coerce.coerce(expr_ty, target_ty) else {
return false;
};
Expand Down Expand Up @@ -1261,8 +1238,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
new: &hir::Expr<'_>,
new_ty: Ty<'tcx>,
) -> RelateResult<'tcx, Ty<'tcx>> {
let prev_ty = self.try_structurally_resolve_type(cause.span, prev_ty);
let new_ty = self.try_structurally_resolve_type(new.span, new_ty);
let prev_ty = self.resolve_vars_with_obligations(prev_ty);
let new_ty = self.resolve_vars_with_obligations(new_ty);
debug!(
"coercion::try_find_coercion_lub({:?}, {:?}, exprs={:?} exprs)",
prev_ty,
Expand Down
6 changes: 1 addition & 5 deletions compiler/rustc_hir_typeck/src/demand.rs
Original file line number Diff line number Diff line change
Expand Up @@ -260,11 +260,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
mut expected_ty_expr: Option<&'tcx hir::Expr<'tcx>>,
allow_two_phase: AllowTwoPhase,
) -> Result<Ty<'tcx>, Diag<'a>> {
let expected = if self.next_trait_solver() {
expected
} else {
self.resolve_vars_with_obligations(expected)
};
let expected = self.resolve_vars_with_obligations(expected);

let e = match self.coerce(expr, checked_ty, expected, allow_two_phase, None) {
Ok(ty) => return Ok(ty),
Expand Down
3 changes: 1 addition & 2 deletions compiler/rustc_hir_typeck/src/expectation.rs
Original file line number Diff line number Diff line change
Expand Up @@ -43,11 +43,10 @@ impl<'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.try_structurally_resolve_type(span, ety);
let ety = fcx.resolve_vars_with_obligations(ety);
if !ety.is_ty_var() { ExpectHasType(ety) } else { NoExpectation }
}
ExpectRvalueLikeUnsized(ety) => ExpectRvalueLikeUnsized(ety),
Expand Down
Loading
Loading