Skip to content

Commit 2ac7ec3

Browse files
Auto merge of #133502 - lcnr:rust4, r=<try>
[DO NOT MERGE] bootstrap with `-Znext-solver=globally`
2 parents 32e3d9f + b32819b commit 2ac7ec3

File tree

102 files changed

+1432
-577
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

102 files changed

+1432
-577
lines changed

compiler/rustc_ast_passes/src/feature_gate.rs

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
use rustc_ast as ast;
22
use rustc_ast::visit::{self, AssocCtxt, FnCtxt, FnKind, Visitor};
33
use rustc_ast::{NodeId, PatKind, attr, token};
4+
use rustc_errors::E0001;
45
use rustc_feature::{AttributeGate, BUILTIN_ATTRIBUTE_MAP, BuiltinAttribute, Features};
56
use rustc_session::Session;
67
use rustc_session::parse::{feature_err, feature_warn};
@@ -654,10 +655,13 @@ fn check_new_solver_banned_features(sess: &Session, features: &Features) {
654655
.map(|feat| feat.attr_sp)
655656
{
656657
#[allow(rustc::symbol_intern_string_literal)]
657-
sess.dcx().emit_err(errors::IncompatibleFeatures {
658-
spans: vec![gce_span],
659-
f1: Symbol::intern("-Znext-solver=globally"),
660-
f2: sym::generic_const_exprs,
661-
});
658+
sess.dcx()
659+
.create_fatal(errors::IncompatibleFeatures {
660+
spans: vec![gce_span],
661+
f1: Symbol::intern("-Znext-solver=globally"),
662+
f2: sym::generic_const_exprs,
663+
})
664+
.with_code(E0001)
665+
.emit();
662666
}
663667
}

compiler/rustc_hir_analysis/src/autoderef.rs

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -68,7 +68,14 @@ impl<'a, 'tcx> Iterator for Autoderef<'a, 'tcx> {
6868
return None;
6969
}
7070

71-
if self.state.cur_ty.is_ty_var() {
71+
// We want to support method and function calls for `impl Deref<Target = ..>`.
72+
//
73+
// To do so we don't eagerly bail if the current type is the hidden type of an
74+
// opaque type and instead return `None` in `fn overloaded_deref_ty` if the
75+
// opaque does not have a `Deref` item-bound.
76+
if let &ty::Infer(ty::TyVar(vid)) = self.state.cur_ty.kind()
77+
&& !self.infcx.has_opaques_with_sub_unified_hidden_type(vid)
78+
{
7279
return None;
7380
}
7481

@@ -160,7 +167,11 @@ impl<'a, 'tcx> Autoderef<'a, 'tcx> {
160167
self.param_env,
161168
ty::Binder::dummy(trait_ref),
162169
);
163-
if !self.infcx.next_trait_solver() && !self.infcx.predicate_may_hold(&obligation) {
170+
// We detect whether the self type implements `Deref` before trying to
171+
// structurally normalize. We use `predicate_may_hold_opaque_types_jank`
172+
// to support not-yet-defined opaque types. It will succeed for `impl Deref`
173+
// but fail for `impl OtherTrait`.
174+
if !self.infcx.predicate_may_hold_opaque_types_jank(&obligation) {
164175
debug!("overloaded_deref_ty: cannot match obligation");
165176
return None;
166177
}

compiler/rustc_hir_typeck/src/callee.rs

Lines changed: 22 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ use tracing::{debug, instrument};
2525
use super::method::MethodCallee;
2626
use super::method::probe::ProbeScope;
2727
use super::{Expectation, FnCtxt, TupleArgumentsFlag};
28+
use crate::method::TreatNotYetDefinedOpaques;
2829
use crate::{errors, fluent_generated};
2930

3031
/// Checks that it is legal to call methods of the trait corresponding
@@ -78,7 +79,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
7879
_ => self.check_expr(callee_expr),
7980
};
8081

81-
let expr_ty = self.structurally_resolve_type(call_expr.span, original_callee_ty);
82+
let expr_ty = self.try_structurally_resolve_type(call_expr.span, original_callee_ty);
8283

8384
let mut autoderef = self.autoderef(callee_expr.span, expr_ty);
8485
let mut result = None;
@@ -200,7 +201,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
200201
arg_exprs: &'tcx [hir::Expr<'tcx>],
201202
autoderef: &Autoderef<'a, 'tcx>,
202203
) -> Option<CallStep<'tcx>> {
203-
let adjusted_ty = self.structurally_resolve_type(autoderef.span(), autoderef.final_ty());
204+
let adjusted_ty =
205+
self.try_structurally_resolve_type(autoderef.span(), autoderef.final_ty());
204206

205207
// If the callee is a function pointer or a closure, then we're all set.
206208
match *adjusted_ty.kind() {
@@ -297,6 +299,15 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
297299
return None;
298300
}
299301

302+
ty::Infer(ty::TyVar(vid)) => {
303+
// If we end up with an inference variable which is not the hidden type of
304+
// an opaque, emit an error.
305+
if !self.has_opaques_with_sub_unified_hidden_type(vid) {
306+
self.type_must_be_known_at_this_point(autoderef.span(), adjusted_ty);
307+
return None;
308+
}
309+
}
310+
300311
ty::Error(_) => {
301312
return None;
302313
}
@@ -367,26 +378,33 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
367378
Ty::new_tup_from_iter(self.tcx, arg_exprs.iter().map(|e| self.next_ty_var(e.span)))
368379
});
369380

381+
// We use `TreatNotYetDefinedOpaques::AsRigid` here so that if the `adjusted_ty`
382+
// is `Box<impl FnOnce()>` we choose `FnOnce` instead of `Fn`.
383+
//
384+
// We try all the different call traits in order and choose the first
385+
// one which may apply. So if we treat opaques as inference variables
386+
// `Box<impl FnOnce()>: Fn` is considered ambiguous and chosen.
370387
if let Some(ok) = self.lookup_method_for_operator(
371388
self.misc(call_expr.span),
372389
method_name,
373390
trait_def_id,
374391
adjusted_ty,
375392
opt_input_type,
393+
TreatNotYetDefinedOpaques::AsRigid,
376394
) {
377395
let method = self.register_infer_ok_obligations(ok);
378396
let mut autoref = None;
379397
if borrow {
380398
// Check for &self vs &mut self in the method signature. Since this is either
381399
// the Fn or FnMut trait, it should be one of those.
382-
let ty::Ref(_, _, mutbl) = method.sig.inputs()[0].kind() else {
400+
let ty::Ref(_, _, mutbl) = *method.sig.inputs()[0].kind() else {
383401
bug!("Expected `FnMut`/`Fn` to take receiver by-ref/by-mut")
384402
};
385403

386404
// For initial two-phase borrow
387405
// deployment, conservatively omit
388406
// overloaded function call ops.
389-
let mutbl = AutoBorrowMutability::new(*mutbl, AllowTwoPhase::No);
407+
let mutbl = AutoBorrowMutability::new(mutbl, AllowTwoPhase::No);
390408

391409
autoref = Some(Adjustment {
392410
kind: Adjust::Borrow(AutoBorrow::Ref(mutbl)),

compiler/rustc_hir_typeck/src/closure.rs

Lines changed: 74 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -9,17 +9,18 @@ use rustc_hir as hir;
99
use rustc_hir::lang_items::LangItem;
1010
use rustc_hir_analysis::hir_ty_lowering::HirTyLowerer;
1111
use rustc_infer::infer::{BoundRegionConversionTime, DefineOpaqueTypes, InferOk, InferResult};
12-
use rustc_infer::traits::{ObligationCauseCode, PredicateObligations};
12+
use rustc_infer::traits::{ObligationCause, ObligationCauseCode, PredicateObligations};
1313
use rustc_macros::{TypeFoldable, TypeVisitable};
1414
use rustc_middle::span_bug;
15+
use rustc_middle::ty::error::TypeError;
1516
use rustc_middle::ty::{
16-
self, ClosureKind, GenericArgs, Ty, TyCtxt, TypeSuperVisitable, TypeVisitable,
17-
TypeVisitableExt, TypeVisitor,
17+
self, ClosureKind, GenericArgs, Ty, TyCtxt, TypeFoldable, TypeFolder, TypeSuperFoldable,
18+
TypeSuperVisitable, TypeVisitable, TypeVisitableExt, TypeVisitor,
1819
};
1920
use rustc_span::def_id::LocalDefId;
2021
use rustc_span::{DUMMY_SP, Span};
2122
use rustc_trait_selection::error_reporting::traits::ArgKind;
22-
use rustc_trait_selection::traits;
23+
use rustc_trait_selection::traits::{self, ObligationCtxt};
2324
use tracing::{debug, instrument, trace};
2425

2526
use super::{CoroutineTypes, Expectation, FnCtxt, check_fn};
@@ -384,56 +385,83 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
384385
// Make sure that we didn't infer a signature that mentions itself.
385386
// This can happen when we elaborate certain supertrait bounds that
386387
// mention projections containing the `Self` type. See #105401.
387-
struct MentionsTy<'tcx> {
388-
expected_ty: Ty<'tcx>,
389-
}
390-
impl<'tcx> TypeVisitor<TyCtxt<'tcx>> for MentionsTy<'tcx> {
391-
type Result = ControlFlow<()>;
392-
393-
fn visit_ty(&mut self, t: Ty<'tcx>) -> Self::Result {
394-
if t == self.expected_ty {
395-
ControlFlow::Break(())
396-
} else {
397-
t.super_visit_with(self)
398-
}
399-
}
400-
}
401-
402-
// Don't infer a closure signature from a goal that names the closure type as this will
403-
// (almost always) lead to occurs check errors later in type checking.
388+
//
389+
// Doing so will (almost always) lead to occurs check errors later in
390+
// type checking.
404391
if self.next_trait_solver()
405392
&& let Some(inferred_sig) = inferred_sig
406393
{
407-
// In the new solver it is difficult to explicitly normalize the inferred signature as we
408-
// would have to manually handle universes and rewriting bound vars and placeholders back
409-
// and forth.
410-
//
411-
// Instead we take advantage of the fact that we relating an inference variable with an alias
412-
// will only instantiate the variable if the alias is rigid(*not quite). Concretely we:
413-
// - Create some new variable `?sig`
414-
// - Equate `?sig` with the unnormalized signature, e.g. `fn(<Foo<?x> as Trait>::Assoc)`
415-
// - Depending on whether `<Foo<?x> as Trait>::Assoc` is rigid, ambiguous or normalizeable,
416-
// we will either wind up with `?sig=<Foo<?x> as Trait>::Assoc/?y/ConcreteTy` respectively.
417-
//
418-
// *: In cases where there are ambiguous aliases in the signature that make use of bound vars
419-
// they will wind up present in `?sig` even though they are non-rigid.
394+
// If we've got `F: FnOnce(<u32 as Id<F>>::This)` we want to
395+
// use this to infer the signature `FnOnce(u32)` for the closure.
420396
//
421-
// This is a bit weird and means we may wind up discarding the goal due to it naming `expected_ty`
422-
// even though the normalized form may not name `expected_ty`. However, this matches the existing
423-
// behaviour of the old solver and would be technically a breaking change to fix.
397+
// We handle self-referential aliases here by relying on generalization
398+
// which replaces such aliases with inference variables. This is currently
399+
// a bit too weak, see trait-system-refactor-initiative#191.
400+
struct ReplaceTy<'tcx> {
401+
tcx: TyCtxt<'tcx>,
402+
expected_ty: Ty<'tcx>,
403+
with_ty: Ty<'tcx>,
404+
}
405+
impl<'tcx> TypeFolder<TyCtxt<'tcx>> for ReplaceTy<'tcx> {
406+
fn cx(&self) -> TyCtxt<'tcx> {
407+
self.tcx
408+
}
409+
410+
fn fold_ty(&mut self, t: Ty<'tcx>) -> Ty<'tcx> {
411+
if t == self.expected_ty {
412+
self.with_ty
413+
} else {
414+
t.super_fold_with(self)
415+
}
416+
}
417+
}
424418
let generalized_fnptr_sig = self.next_ty_var(span);
425419
let inferred_fnptr_sig = Ty::new_fn_ptr(self.tcx, inferred_sig.sig);
426-
self.demand_eqtype(span, inferred_fnptr_sig, generalized_fnptr_sig);
427-
428-
let resolved_sig = self.resolve_vars_if_possible(generalized_fnptr_sig);
429-
430-
if resolved_sig.visit_with(&mut MentionsTy { expected_ty }).is_continue() {
431-
expected_sig = Some(ExpectedSig {
432-
cause_span: inferred_sig.cause_span,
433-
sig: resolved_sig.fn_sig(self.tcx),
434-
});
420+
let inferred_fnptr_sig = inferred_fnptr_sig.fold_with(&mut ReplaceTy {
421+
tcx: self.tcx,
422+
expected_ty,
423+
with_ty: generalized_fnptr_sig,
424+
});
425+
let resolved_sig = self.fudge_inference_if_ok(|snapshot| {
426+
let outer_universe = self.universe();
427+
let ocx = ObligationCtxt::new(self);
428+
ocx.eq(
429+
&ObligationCause::dummy(),
430+
self.param_env,
431+
generalized_fnptr_sig,
432+
inferred_fnptr_sig,
433+
)?;
434+
if ocx.select_where_possible().is_empty() {
435+
self.leak_check(outer_universe, Some(snapshot))?;
436+
Ok(self.resolve_vars_if_possible(generalized_fnptr_sig))
437+
} else {
438+
Err(TypeError::Mismatch)
439+
}
440+
});
441+
match resolved_sig {
442+
Ok(resolved_sig) => {
443+
expected_sig = Some(ExpectedSig {
444+
cause_span: inferred_sig.cause_span,
445+
sig: resolved_sig.fn_sig(self.tcx),
446+
})
447+
}
448+
Err(_) => {}
435449
}
436450
} else {
451+
struct MentionsTy<'tcx> {
452+
expected_ty: Ty<'tcx>,
453+
}
454+
impl<'tcx> TypeVisitor<TyCtxt<'tcx>> for MentionsTy<'tcx> {
455+
type Result = ControlFlow<()>;
456+
457+
fn visit_ty(&mut self, t: Ty<'tcx>) -> Self::Result {
458+
if t == self.expected_ty {
459+
ControlFlow::Break(())
460+
} else {
461+
t.super_visit_with(self)
462+
}
463+
}
464+
}
437465
if inferred_sig.visit_with(&mut MentionsTy { expected_ty }).is_continue() {
438466
expected_sig = inferred_sig;
439467
}

compiler/rustc_hir_typeck/src/expr.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1634,7 +1634,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
16341634
) -> Ty<'tcx> {
16351635
let rcvr_t = self.check_expr(rcvr);
16361636
// no need to check for bot/err -- callee does that
1637-
let rcvr_t = self.structurally_resolve_type(rcvr.span, rcvr_t);
1637+
let rcvr_t = self.try_structurally_resolve_type(rcvr.span, rcvr_t);
16381638

16391639
match self.lookup_method(rcvr_t, segment, segment.ident.span, expr, rcvr, args) {
16401640
Ok(method) => {
@@ -2015,7 +2015,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
20152015

20162016
let adt_ty = self.try_structurally_resolve_type(path_span, adt_ty);
20172017
let adt_ty_hint = expected.only_has_type(self).and_then(|expected| {
2018-
self.fudge_inference_if_ok(|| {
2018+
self.fudge_inference_if_ok(|_| {
20192019
let ocx = ObligationCtxt::new(self);
20202020
ocx.sup(&self.misc(path_span), self.param_env, expected, adt_ty)?;
20212021
if !ocx.select_where_possible().is_empty() {

compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs

Lines changed: 19 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -1469,24 +1469,25 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
14691469
pub(crate) fn structurally_resolve_type(&self, sp: Span, ty: Ty<'tcx>) -> Ty<'tcx> {
14701470
let ty = self.try_structurally_resolve_type(sp, ty);
14711471

1472-
if !ty.is_ty_var() {
1473-
ty
1474-
} else {
1475-
let e = self.tainted_by_errors().unwrap_or_else(|| {
1476-
self.err_ctxt()
1477-
.emit_inference_failure_err(
1478-
self.body_id,
1479-
sp,
1480-
ty.into(),
1481-
TypeAnnotationNeeded::E0282,
1482-
true,
1483-
)
1484-
.emit()
1485-
});
1486-
let err = Ty::new_error(self.tcx, e);
1487-
self.demand_suptype(sp, err, ty);
1488-
err
1489-
}
1472+
if !ty.is_ty_var() { ty } else { self.type_must_be_known_at_this_point(sp, ty) }
1473+
}
1474+
1475+
#[cold]
1476+
pub(crate) fn type_must_be_known_at_this_point(&self, sp: Span, ty: Ty<'tcx>) -> Ty<'tcx> {
1477+
let guar = self.tainted_by_errors().unwrap_or_else(|| {
1478+
self.err_ctxt()
1479+
.emit_inference_failure_err(
1480+
self.body_id,
1481+
sp,
1482+
ty.into(),
1483+
TypeAnnotationNeeded::E0282,
1484+
true,
1485+
)
1486+
.emit()
1487+
});
1488+
let err = Ty::new_error(self.tcx, guar);
1489+
self.demand_suptype(sp, err, ty);
1490+
err
14901491
}
14911492

14921493
pub(crate) fn structurally_resolve_const(

compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -246,7 +246,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
246246
let expected_input_tys: Option<Vec<_>> = expectation
247247
.only_has_type(self)
248248
.and_then(|expected_output| {
249-
self.fudge_inference_if_ok(|| {
249+
self.fudge_inference_if_ok(|_| {
250250
let ocx = ObligationCtxt::new(self);
251251

252252
// Attempt to apply a subtyping relationship between the formal

compiler/rustc_hir_typeck/src/fn_ctxt/inspect_obligations.rs

Lines changed: 1 addition & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
//! A utility module to inspect currently ambiguous obligations in the current context.
22
33
use rustc_infer::traits::{self, ObligationCause, PredicateObligations};
4-
use rustc_middle::traits::solve::GoalSource;
54
use rustc_middle::ty::{self, Ty, TypeVisitableExt};
65
use rustc_span::Span;
76
use rustc_trait_selection::solve::Certainty;
@@ -127,21 +126,7 @@ impl<'a, 'tcx> ProofTreeVisitor<'tcx> for NestedObligationsForSelfTy<'a, 'tcx> {
127126

128127
let tcx = self.fcx.tcx;
129128
let goal = inspect_goal.goal();
130-
if self.fcx.predicate_has_self_ty(goal.predicate, self.self_ty)
131-
// We do not push the instantiated forms of goals as it would cause any
132-
// aliases referencing bound vars to go from having escaping bound vars to
133-
// being able to be normalized to an inference variable.
134-
//
135-
// This is mostly just a hack as arbitrary nested goals could still contain
136-
// such aliases while having a different `GoalSource`. Closure signature inference
137-
// however can't really handle *every* higher ranked `Fn` goal also being present
138-
// in the form of `?c: Fn<(<?x as Trait<'!a>>::Assoc)`.
139-
//
140-
// This also just better matches the behaviour of the old solver where we do not
141-
// encounter instantiated forms of goals, only nested goals that referred to bound
142-
// vars from instantiated goals.
143-
&& !matches!(inspect_goal.source(), GoalSource::InstantiateHigherRanked)
144-
{
129+
if self.fcx.predicate_has_self_ty(goal.predicate, self.self_ty) {
145130
self.obligations_for_self_ty.push(traits::Obligation::new(
146131
tcx,
147132
self.root_cause.clone(),

compiler/rustc_hir_typeck/src/method/confirm.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -182,7 +182,7 @@ impl<'a, 'tcx> ConfirmContext<'a, 'tcx> {
182182
assert_eq!(n, pick.autoderefs);
183183

184184
let mut adjustments = self.adjust_steps(&autoderef);
185-
let mut target = self.structurally_resolve_type(autoderef.span(), ty);
185+
let mut target = self.try_structurally_resolve_type(autoderef.span(), ty);
186186

187187
match pick.autoref_or_ptr_adjustment {
188188
Some(probe::AutorefOrPtrAdjustment::Autoref { mutbl, unsize }) => {

0 commit comments

Comments
 (0)