Skip to content

Commit 62810ce

Browse files
Auto merge of #133502 - lcnr:rust4, r=<try>
[DO NOT MERGE] bootstrap with `-Znext-solver=globally` try-job: x86_64-fuchsia
2 parents bd34871 + 89b6176 commit 62810ce

File tree

50 files changed

+624
-373
lines changed

Some content is hidden

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

50 files changed

+624
-373
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};
@@ -650,10 +651,13 @@ fn check_new_solver_banned_features(sess: &Session, features: &Features) {
650651
.map(|feat| feat.attr_sp)
651652
{
652653
#[allow(rustc::symbol_intern_string_literal)]
653-
sess.dcx().emit_err(errors::IncompatibleFeatures {
654-
spans: vec![gce_span],
655-
f1: Symbol::intern("-Znext-solver=globally"),
656-
f2: sym::generic_const_exprs,
657-
});
654+
sess.dcx()
655+
.create_fatal(errors::IncompatibleFeatures {
656+
spans: vec![gce_span],
657+
f1: Symbol::intern("-Znext-solver=globally"),
658+
f2: sym::generic_const_exprs,
659+
})
660+
.with_code(E0001)
661+
.emit();
658662
}
659663
}

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.commit_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/fn_ctxt/inspect_obligations.rs

Lines changed: 21 additions & 20 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;
@@ -37,10 +36,10 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
3736
) -> bool {
3837
match predicate.kind().skip_binder() {
3938
ty::PredicateKind::Clause(ty::ClauseKind::Trait(data)) => {
40-
self.type_matches_expected_vid(expected_vid, data.self_ty())
39+
self.type_matches_expected_vid(data.self_ty(), expected_vid)
4140
}
4241
ty::PredicateKind::Clause(ty::ClauseKind::Projection(data)) => {
43-
self.type_matches_expected_vid(expected_vid, data.projection_term.self_ty())
42+
self.type_matches_expected_vid(data.projection_term.self_ty(), expected_vid)
4443
}
4544
ty::PredicateKind::Clause(ty::ClauseKind::ConstArgHasType(..))
4645
| ty::PredicateKind::Subtype(..)
@@ -60,7 +59,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
6059
}
6160

6261
#[instrument(level = "debug", skip(self), ret)]
63-
fn type_matches_expected_vid(&self, expected_vid: ty::TyVid, ty: Ty<'tcx>) -> bool {
62+
fn type_matches_expected_vid(&self, ty: Ty<'tcx>, expected_vid: ty::TyVid) -> bool {
6463
let ty = self.shallow_resolve(ty);
6564
debug!(?ty);
6665

@@ -76,7 +75,11 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
7675
&self,
7776
self_ty: ty::TyVid,
7877
) -> PredicateObligations<'tcx> {
79-
let obligations = self.fulfillment_cx.borrow().pending_obligations();
78+
let sub_root_var = self.sub_unification_table_root_var(self_ty);
79+
let obligations = self
80+
.fulfillment_cx
81+
.borrow()
82+
.pending_obligations_potentially_referencing_sub_root(sub_root_var);
8083
debug!(?obligations);
8184
let mut obligations_for_self_ty = PredicateObligations::new();
8285
for obligation in obligations {
@@ -125,23 +128,21 @@ impl<'a, 'tcx> ProofTreeVisitor<'tcx> for NestedObligationsForSelfTy<'a, 'tcx> {
125128
return;
126129
}
127130

131+
// We don't care about any pending goals which don't actually
132+
// use the self type.
133+
if !inspect_goal
134+
.orig_values()
135+
.iter()
136+
.filter_map(|arg| arg.as_type())
137+
.any(|ty| self.fcx.type_matches_expected_vid(ty, self.self_ty))
138+
{
139+
debug!(goal = ?inspect_goal.goal(), "goal does not mention self type");
140+
return;
141+
}
142+
128143
let tcx = self.fcx.tcx;
129144
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-
{
145+
if self.fcx.predicate_has_self_ty(goal.predicate, self.self_ty) {
145146
self.obligations_for_self_ty.push(traits::Obligation::new(
146147
tcx,
147148
self.root_cause.clone(),

compiler/rustc_hir_typeck/src/lib.rs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -219,6 +219,12 @@ fn typeck_with_inspect<'tcx>(
219219
// the future.
220220
fcx.check_repeat_exprs();
221221

222+
// We need to handle opaque types before emitting ambiguity errors as applying
223+
// defining uses may guide type inference.
224+
if fcx.next_trait_solver() {
225+
fcx.try_handle_opaque_type_uses_next();
226+
}
227+
222228
fcx.type_inference_fallback();
223229

224230
// Even though coercion casts provide type hints, we check casts after fallback for

compiler/rustc_hir_typeck/src/opaque_types.rs

Lines changed: 50 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,29 @@ impl<'tcx> FnCtxt<'_, 'tcx> {
2222
/// inference variables.
2323
///
2424
/// It then uses these defining uses to guide inference for all other uses.
25+
///
26+
/// Unlike `handle_opaque_type_uses_next`, this does not report errors.
27+
pub(super) fn try_handle_opaque_type_uses_next(&mut self) {
28+
// We clone the opaques instead of stealing them here as they are still used for
29+
// normalization in the next generation trait solver.
30+
let mut opaque_types: Vec<_> = self.infcx.clone_opaque_types();
31+
for entry in &mut opaque_types {
32+
*entry = self.resolve_vars_if_possible(*entry);
33+
}
34+
debug!(?opaque_types);
35+
36+
self.compute_definition_site_hidden_types(&opaque_types, true);
37+
self.apply_definition_site_hidden_types(&opaque_types);
38+
}
39+
40+
/// This takes all the opaque type uses during HIR typeck. It first computes
41+
/// the concrete hidden type by iterating over all defining uses.
42+
///
43+
/// A use during HIR typeck is defining if all non-lifetime arguments are
44+
/// unique generic parameters and the hidden type does not reference any
45+
/// inference variables.
46+
///
47+
/// It then uses these defining uses to guide inference for all other uses.
2548
#[instrument(level = "debug", skip(self))]
2649
pub(super) fn handle_opaque_type_uses_next(&mut self) {
2750
// We clone the opaques instead of stealing them here as they are still used for
@@ -35,7 +58,7 @@ impl<'tcx> FnCtxt<'_, 'tcx> {
3558
}
3659
debug!(?opaque_types);
3760

38-
self.compute_definition_site_hidden_types(&opaque_types);
61+
self.compute_definition_site_hidden_types(&opaque_types, false);
3962
self.apply_definition_site_hidden_types(&opaque_types);
4063
}
4164
}
@@ -74,6 +97,7 @@ impl<'tcx> FnCtxt<'_, 'tcx> {
7497
fn compute_definition_site_hidden_types(
7598
&mut self,
7699
opaque_types: &[(OpaqueTypeKey<'tcx>, OpaqueHiddenType<'tcx>)],
100+
first_pass: bool,
77101
) {
78102
let tcx = self.tcx;
79103
let TypingMode::Analysis { defining_opaque_types_and_generators } = self.typing_mode()
@@ -94,12 +118,22 @@ impl<'tcx> FnCtxt<'_, 'tcx> {
94118
continue;
95119
}
96120

97-
usage_kind.merge(self.consider_opaque_type_use(opaque_type_key, hidden_type));
121+
usage_kind.merge(self.consider_opaque_type_use(
122+
opaque_type_key,
123+
hidden_type,
124+
first_pass,
125+
));
98126
if let UsageKind::HasDefiningUse = usage_kind {
99127
break;
100128
}
101129
}
102130

131+
// If this the first pass (`try_handle_opaque_type_uses_next`),
132+
// then do not report any errors.
133+
if first_pass {
134+
continue;
135+
}
136+
103137
let guar = match usage_kind {
104138
UsageKind::None => {
105139
if let Some(guar) = self.tainted_by_errors() {
@@ -152,6 +186,7 @@ impl<'tcx> FnCtxt<'_, 'tcx> {
152186
&mut self,
153187
opaque_type_key: OpaqueTypeKey<'tcx>,
154188
hidden_type: OpaqueHiddenType<'tcx>,
189+
first_pass: bool,
155190
) -> UsageKind<'tcx> {
156191
if let Err(err) = opaque_type_has_defining_use_args(
157192
&self,
@@ -199,7 +234,13 @@ impl<'tcx> FnCtxt<'_, 'tcx> {
199234
.borrow_mut()
200235
.hidden_types
201236
.insert(opaque_type_key.def_id, hidden_type);
202-
assert!(prev.is_none());
237+
238+
// We do want to insert opaque types the first pass, because we want to
239+
// equate them. So, the second pass (where we report errors) will have
240+
// a hidden type inserted.
241+
if first_pass {
242+
assert!(prev.is_none());
243+
}
203244
UsageKind::HasDefiningUse
204245
}
205246

@@ -209,10 +250,12 @@ impl<'tcx> FnCtxt<'_, 'tcx> {
209250
) {
210251
let tcx = self.tcx;
211252
for &(key, hidden_type) in opaque_types {
212-
let expected = *self.typeck_results.borrow_mut().hidden_types.get(&key.def_id).unwrap();
213-
214-
let expected = EarlyBinder::bind(expected.ty).instantiate(tcx, key.args);
215-
self.demand_eqtype(hidden_type.span, expected, hidden_type.ty);
253+
// On the first pass to this function, some opaque types may not
254+
// have a hidden type assigned.
255+
if let Some(expected) = self.typeck_results.borrow_mut().hidden_types.get(&key.def_id) {
256+
let expected = EarlyBinder::bind(expected.ty).instantiate(tcx, key.args);
257+
self.demand_eqtype(hidden_type.span, expected, hidden_type.ty);
258+
}
216259
}
217260
}
218261

0 commit comments

Comments
 (0)