Skip to content

Commit

Permalink
Auto merge of rust-lang#133502 - lcnr:rust4, r=<try>
Browse files Browse the repository at this point in the history
[DO NOT MERGE] bootstrap with `-Znext-solver=globally`

A revival of rust-lang#124812.

Current status:

`./x.py b --stage 2` passes 🎉

### commits

- rust-lang#133501
- rust-lang#133493
- 9456bfe and b21b116 reimplement candidate preference based on rust-lang#132325, not yet a separate PR
- c3ef9cd is a rebased version of rust-lang#125334, unsure whether I actually want to land this PR for now
- rust-lang#133517
* rust-lang#133518
* rust-lang#133519
* rust-lang#133520
* rust-lang#133521
* rust-lang#133524

r? `@ghost`
  • Loading branch information
bors committed Nov 27, 2024
2 parents 6b6a867 + 8fa8f40 commit 550ae0d
Show file tree
Hide file tree
Showing 56 changed files with 896 additions and 237 deletions.
36 changes: 36 additions & 0 deletions compiler/rustc_borrowck/src/type_check/canonical.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ use rustc_middle::mir::ConstraintCategory;
use rustc_middle::ty::{self, Ty, TyCtxt, TypeFoldable, 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};
Expand Down Expand Up @@ -177,6 +178,7 @@ impl<'a, 'tcx> TypeChecker<'a, '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,
Expand Down Expand Up @@ -213,6 +215,40 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
}
}

#[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(
&ObligationCause::misc(
location.to_locations().span(body),
body.source.def_id().expect_local(),
),
param_env,
ty,
)
.map_err(|_| NoSolution)
},
"normalizing struct tail",
),
)
.unwrap_or_else(|guar| Ty::new_error(self.tcx(), guar))
} else {
self.normalize(ty, location)
}
}

#[instrument(skip(self), level = "debug")]
pub(super) fn ascribe_user_type(
&mut self,
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 @@ -1075,7 +1075,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
proj,
|this, field, ()| {
let ty = this.field_ty(tcx, field);
self.normalize(ty, locations)
self.structurally_resolve(ty, locations)
},
|_, _| unreachable!(),
);
Expand Down
14 changes: 11 additions & 3 deletions compiler/rustc_hir_analysis/src/check/check.rs
Original file line number Diff line number Diff line change
Expand Up @@ -322,8 +322,12 @@ fn check_opaque_meets_bounds<'tcx>(
};
let param_env = tcx.param_env(defining_use_anchor);

// FIXME(#132279): This should eventually use the already defined hidden types.
let infcx = tcx.infer_ctxt().build(TypingMode::analysis_in_body(tcx, defining_use_anchor));
// FIXME(#132279): Once `PostBorrowckAnalysis` is supported in the old solver, this branch should be removed.
let infcx = tcx.infer_ctxt().build(if tcx.next_trait_solver_globally() {
TypingMode::post_borrowck_analysis(tcx, defining_use_anchor)
} else {
TypingMode::analysis_in_body(tcx, defining_use_anchor)
});
let ocx = ObligationCtxt::new_with_diagnostics(&infcx);

let args = match origin {
Expand Down Expand Up @@ -417,7 +421,11 @@ fn check_opaque_meets_bounds<'tcx>(
let outlives_env = OutlivesEnvironment::with_bounds(param_env, implied_bounds);
ocx.resolve_regions_and_report_errors(defining_use_anchor, &outlives_env)?;

if let hir::OpaqueTyOrigin::FnReturn { .. } | hir::OpaqueTyOrigin::AsyncFn { .. } = origin {
if infcx.next_trait_solver() {
Ok(())
} else if let hir::OpaqueTyOrigin::FnReturn { .. } | hir::OpaqueTyOrigin::AsyncFn { .. } =
origin
{
// HACK: this should also fall through to the hidden type check below, but the original
// implementation had a bug where equivalent lifetimes are not identical. This caused us
// to reject existing stable code that is otherwise completely fine. The real fix is to
Expand Down
2 changes: 1 addition & 1 deletion compiler/rustc_hir_typeck/src/_match.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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 = {
Expand Down
8 changes: 6 additions & 2 deletions compiler/rustc_hir_typeck/src/expectation.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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),
Expand Down
10 changes: 7 additions & 3 deletions compiler/rustc_hir_typeck/src/expr.rs
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {

// While we don't allow *arbitrary* coercions here, we *do* allow
// coercions from ! to `expected`.
if ty.is_never() && self.expr_guaranteed_to_constitute_read_for_never(expr) {
if self.try_structurally_resolve_type(expr.span, ty).is_never()
&& self.expr_guaranteed_to_constitute_read_for_never(expr)
{
if let Some(_) = self.typeck_results.borrow().adjustments().get(expr.hir_id) {
let reported = self.dcx().span_delayed_bug(
expr.span,
Expand Down Expand Up @@ -274,7 +276,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
// unless it's a place expression that isn't being read from, in which case
// diverging would be unsound since we may never actually read the `!`.
// e.g. `let _ = *never_ptr;` with `never_ptr: *const !`.
if ty.is_never() && self.expr_guaranteed_to_constitute_read_for_never(expr) {
if self.try_structurally_resolve_type(expr.span, ty).is_never()
&& self.expr_guaranteed_to_constitute_read_for_never(expr)
{
self.diverges.set(self.diverges.get() | Diverges::always(expr.span));
}

Expand Down Expand Up @@ -1290,7 +1294,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);
Expand Down
22 changes: 21 additions & 1 deletion compiler/rustc_hir_typeck/src/method/probe.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1574,7 +1574,8 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> {
// Thus we need to prevent them from trying to match the `&_` autoref
// candidates that get created for `&self` trait methods.
ty::Alias(ty::Opaque, alias_ty)
if self.infcx.can_define_opaque_ty(alias_ty.def_id)
if !self.next_trait_solver()
&& self.infcx.can_define_opaque_ty(alias_ty.def_id)
&& !xform_self_ty.is_ty_var() =>
{
return ProbeResult::NoMatch;
Expand Down Expand Up @@ -1642,6 +1643,25 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> {
}
}

// In the new solver, check the well-formedness of the return type.
// This emulates, in a way, the predicates that fall out of
// normalizing the return type in the old solver.
//
// We alternatively could check the predicates of the method itself hold,
// but we intentionally do not do this in the old solver b/c of cycles,
// and doing it in the new solver would be stronger. This should be fixed
// in the future, since it likely leads to much better method winnowing.
if let Some(xform_ret_ty) = xform_ret_ty
&& self.infcx.next_trait_solver()
{
ocx.register_obligation(traits::Obligation::new(
self.tcx,
cause.clone(),
self.param_env,
ty::ClauseKind::WellFormed(xform_ret_ty.into()),
));
}

// Evaluate those obligations to see if they might possibly hold.
for error in ocx.select_where_possible() {
result = ProbeResult::NoMatch;
Expand Down
9 changes: 7 additions & 2 deletions compiler/rustc_hir_typeck/src/upvar.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1802,7 +1802,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
let mut is_mutbl = bm.1;

for pointer_ty in place.deref_tys() {
match pointer_ty.kind() {
match self.structurally_resolve_type(self.tcx.hir().span(var_hir_id), pointer_ty).kind()
{
// We don't capture derefs of raw ptrs
ty::RawPtr(_, _) => unreachable!(),

Expand All @@ -1816,7 +1817,11 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
// Dereferencing a box doesn't change mutability
ty::Adt(def, ..) if def.is_box() => {}

unexpected_ty => bug!("deref of unexpected pointer type {:?}", unexpected_ty),
unexpected_ty => span_bug!(
self.tcx.hir().span(var_hir_id),
"deref of unexpected pointer type {:?}",
unexpected_ty
),
}
}

Expand Down
6 changes: 5 additions & 1 deletion compiler/rustc_infer/src/infer/context.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ use rustc_middle::ty::relate::combine::PredicateEmittingRelation;
use rustc_middle::ty::{self, Ty, TyCtxt};
use rustc_span::{DUMMY_SP, ErrorGuaranteed};

use super::{BoundRegionConversionTime, InferCtxt, SubregionOrigin};
use super::{BoundRegionConversionTime, InferCtxt, RegionVariableOrigin, SubregionOrigin};

impl<'tcx> rustc_type_ir::InferCtxtLike for InferCtxt<'tcx> {
type Interner = TyCtxt<'tcx>;
Expand Down Expand Up @@ -87,6 +87,10 @@ impl<'tcx> rustc_type_ir::InferCtxtLike for InferCtxt<'tcx> {
self.inner.borrow_mut().unwrap_region_constraints().opportunistic_resolve_var(self.tcx, vid)
}

fn next_region_infer(&self) -> ty::Region<'tcx> {
self.next_region_var(RegionVariableOrigin::MiscVariable(DUMMY_SP))
}

fn next_ty_infer(&self) -> Ty<'tcx> {
self.next_ty_var(DUMMY_SP)
}
Expand Down
13 changes: 10 additions & 3 deletions compiler/rustc_infer/src/infer/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -990,11 +990,17 @@ impl<'tcx> InferCtxt<'tcx> {

#[inline(always)]
pub fn can_define_opaque_ty(&self, id: impl Into<DefId>) -> bool {
debug_assert!(!self.next_trait_solver());
match self.typing_mode() {
TypingMode::Analysis { defining_opaque_types } => {
id.into().as_local().is_some_and(|def_id| defining_opaque_types.contains(&def_id))
}
TypingMode::Coherence | TypingMode::PostAnalysis => false,
// FIXME(#132279): This function is quite weird in post-analysis
// and post-borrowck analysis mode. We may need to modify its uses
// to support PostBorrowckAnalysis in the old solver as well.
TypingMode::Coherence
| TypingMode::PostBorrowckAnalysis { .. }
| TypingMode::PostAnalysis => false,
}
}

Expand Down Expand Up @@ -1276,15 +1282,16 @@ impl<'tcx> InferCtxt<'tcx> {
/// using canonicalization or carrying this inference context around.
pub fn typing_env(&self, param_env: ty::ParamEnv<'tcx>) -> ty::TypingEnv<'tcx> {
let typing_mode = match self.typing_mode() {
ty::TypingMode::Coherence => ty::TypingMode::Coherence,
// FIXME(#132279): This erases the `defining_opaque_types` as it isn't possible
// to handle them without proper canonicalization. This means we may cause cycle
// errors and fail to reveal opaques while inside of bodies. We should rename this
// function and require explicit comments on all use-sites in the future.
ty::TypingMode::Analysis { defining_opaque_types: _ } => {
TypingMode::non_body_analysis()
}
ty::TypingMode::PostAnalysis => ty::TypingMode::PostAnalysis,
mode @ (ty::TypingMode::Coherence
| ty::TypingMode::PostBorrowckAnalysis { .. }
| ty::TypingMode::PostAnalysis) => mode,
};
ty::TypingEnv { typing_mode, param_env }
}
Expand Down
5 changes: 4 additions & 1 deletion compiler/rustc_infer/src/infer/opaque_types/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -98,6 +98,7 @@ impl<'tcx> InferCtxt<'tcx> {
span: Span,
param_env: ty::ParamEnv<'tcx>,
) -> Result<Vec<Goal<'tcx, ty::Predicate<'tcx>>>, TypeError<'tcx>> {
debug_assert!(!self.next_trait_solver());
let process = |a: Ty<'tcx>, b: Ty<'tcx>| match *a.kind() {
ty::Alias(ty::Opaque, ty::AliasTy { def_id, args, .. }) if def_id.is_local() => {
let def_id = def_id.expect_local();
Expand Down Expand Up @@ -546,7 +547,9 @@ impl<'tcx> InferCtxt<'tcx> {
);
}
}
ty::TypingMode::PostAnalysis => bug!("insert hidden type post-analysis"),
mode @ (ty::TypingMode::PostBorrowckAnalysis { .. } | ty::TypingMode::PostAnalysis) => {
bug!("insert hidden type in {mode:?}")
}
}

Ok(())
Expand Down
8 changes: 8 additions & 0 deletions compiler/rustc_middle/src/ty/context.rs
Original file line number Diff line number Diff line change
Expand Up @@ -632,6 +632,14 @@ impl<'tcx> Interner for TyCtxt<'tcx> {
fn opaque_types_defined_by(self, defining_anchor: LocalDefId) -> Self::DefiningOpaqueTypes {
self.opaque_types_defined_by(defining_anchor)
}

fn fold_regions<T: TypeFoldable<TyCtxt<'tcx>>>(
self,
value: T,
f: impl FnMut(ty::Region<'tcx>, ty::DebruijnIndex) -> ty::Region<'tcx>,
) -> T {
self.fold_regions(value, f)
}
}

macro_rules! bidirectional_lang_item_map {
Expand Down
7 changes: 2 additions & 5 deletions compiler/rustc_middle/src/ty/fold.rs
Original file line number Diff line number Diff line change
Expand Up @@ -55,14 +55,11 @@ where

impl<'tcx> TyCtxt<'tcx> {
/// Folds the escaping and free regions in `value` using `f`.
pub fn fold_regions<T>(
pub fn fold_regions<T: TypeFoldable<TyCtxt<'tcx>>>(
self,
value: T,
mut f: impl FnMut(ty::Region<'tcx>, ty::DebruijnIndex) -> ty::Region<'tcx>,
) -> T
where
T: TypeFoldable<TyCtxt<'tcx>>,
{
) -> T {
value.fold_with(&mut RegionFolder::new(self, &mut f))
}
}
Expand Down
7 changes: 6 additions & 1 deletion compiler/rustc_middle/src/ty/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,11 @@ pub use adt::*;
pub use assoc::*;
pub use generic_args::{GenericArgKind, TermKind, *};
pub use generics::*;
// Can't use a glob import here as it would cause
// ambiguity when importing the actual types implementing
// the inherent traits from this module.
#[allow(rustc::non_glob_import_of_type_ir_inherent)]
use inherent::SliceLike;
pub use intrinsic::IntrinsicDef;
use rustc_abi::{Align, FieldIdx, Integer, IntegerType, ReprFlags, ReprOptions, VariantIdx};
use rustc_ast::expand::StrippedCfgItem;
Expand Down Expand Up @@ -970,7 +975,7 @@ pub struct ParamEnv<'tcx> {
}

impl<'tcx> rustc_type_ir::inherent::ParamEnv<TyCtxt<'tcx>> for ParamEnv<'tcx> {
fn caller_bounds(self) -> impl IntoIterator<Item = ty::Clause<'tcx>> {
fn caller_bounds(self) -> impl SliceLike<Item = ty::Clause<'tcx>> {
self.caller_bounds()
}
}
Expand Down
Loading

0 comments on commit 550ae0d

Please sign in to comment.