Skip to content

Commit 943dbaa

Browse files
committed
support revealing uses in HIR typeck
1 parent 2c84bdd commit 943dbaa

File tree

6 files changed

+164
-127
lines changed

6 files changed

+164
-127
lines changed

compiler/rustc_hir_typeck/src/lib.rs

+5-1
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@ mod gather_locals;
3232
mod intrinsicck;
3333
mod method;
3434
mod op;
35+
mod opaque_types;
3536
mod pat;
3637
mod place_op;
3738
mod rvalue_scopes;
@@ -230,8 +231,11 @@ fn typeck_with_inspect<'tcx>(
230231

231232
fcx.select_obligations_where_possible(|_| {});
232233

233-
debug!(pending_obligations = ?fcx.fulfillment_cx.borrow().pending_obligations());
234+
if fcx.next_trait_solver() {
235+
fcx.handle_opaque_type_uses_next();
236+
}
234237

238+
debug!(pending_obligations = ?fcx.fulfillment_cx.borrow().pending_obligations());
235239
// This must be the last thing before `report_ambiguity_errors`.
236240
fcx.resolve_coroutine_interiors();
237241

Original file line numberDiff line numberDiff line change
@@ -0,0 +1,113 @@
1+
use rustc_middle::ty::{
2+
DefiningScopeKind, EarlyBinder, OpaqueHiddenType, OpaqueTypeKey, Ty, TypeVisitableExt,
3+
};
4+
use rustc_trait_selection::opaque_types::{
5+
InvalidOpaqueTypeArgs, check_opaque_type_parameter_valid,
6+
};
7+
8+
use crate::FnCtxt;
9+
impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
10+
pub(super) fn handle_opaque_type_uses_next(&mut self) {
11+
// We clone the opaques instead of stealing them here as they are still used for
12+
// normalization in the next generation trait solver.
13+
//
14+
// FIXME(-Znext-solver): Opaque types defined after this would simply get dropped
15+
// at the end of typeck. Ideally we can feed some query here to no longer define
16+
// new opaque uses but instead always reveal by using the definitions inferred here.
17+
let opaque_types: Vec<_> = self.infcx.clone_opaque_types().into_iter().collect();
18+
self.collect_defining_uses(&opaque_types);
19+
self.apply_defining_uses(&opaque_types);
20+
}
21+
22+
fn collect_defining_uses(
23+
&mut self,
24+
opaque_types: &[(OpaqueTypeKey<'tcx>, OpaqueHiddenType<'tcx>)],
25+
) {
26+
let tcx = self.tcx;
27+
let typeck_results = &mut *self.typeck_results.borrow_mut();
28+
for &(opaque_type_key, hidden_type) in opaque_types {
29+
let opaque_type_key = self.resolve_vars_if_possible(opaque_type_key);
30+
let hidden_type = self.resolve_vars_if_possible(hidden_type);
31+
32+
match check_opaque_type_parameter_valid(
33+
&self,
34+
opaque_type_key,
35+
hidden_type.span,
36+
DefiningScopeKind::HirTypeck,
37+
) {
38+
Ok(()) => {}
39+
Err(InvalidOpaqueTypeArgs::AlreadyReported(guar)) => {
40+
typeck_results
41+
.concrete_opaque_types
42+
.insert(opaque_type_key.def_id, OpaqueHiddenType::new_error(tcx, guar));
43+
}
44+
// Not a defining use, ignore and treat as revealing use instead.
45+
Err(
46+
InvalidOpaqueTypeArgs::NotAParam { .. }
47+
| InvalidOpaqueTypeArgs::DuplicateParam { .. },
48+
) => continue,
49+
}
50+
51+
if hidden_type.ty.has_non_region_infer() {
52+
let guar =
53+
tcx.dcx().span_err(hidden_type.span, "non-defining use in the defining scope");
54+
typeck_results
55+
.concrete_opaque_types
56+
.insert(opaque_type_key.def_id, OpaqueHiddenType::new_error(tcx, guar));
57+
self.set_tainted_by_errors(guar);
58+
}
59+
60+
let hidden_type = hidden_type.remap_generic_params_to_declaration_params(
61+
opaque_type_key,
62+
tcx,
63+
DefiningScopeKind::HirTypeck,
64+
);
65+
66+
if let Some(prev) =
67+
typeck_results.concrete_opaque_types.insert(opaque_type_key.def_id, hidden_type)
68+
{
69+
let entry =
70+
typeck_results.concrete_opaque_types.get_mut(&opaque_type_key.def_id).unwrap();
71+
if prev.ty != hidden_type.ty {
72+
if let Some(guar) = typeck_results.tainted_by_errors {
73+
entry.ty = Ty::new_error(tcx, guar);
74+
} else {
75+
let (Ok(guar) | Err(guar)) =
76+
prev.build_mismatch_error(&hidden_type, tcx).map(|d| d.emit());
77+
entry.ty = Ty::new_error(tcx, guar);
78+
}
79+
}
80+
81+
// Pick a better span if there is one.
82+
// FIXME(oli-obk): collect multiple spans for better diagnostics down the road.
83+
entry.span = prev.span.substitute_dummy(hidden_type.span);
84+
}
85+
}
86+
87+
// FIXME(-Znext-solver): Check that all opaques have been defined hre.
88+
}
89+
90+
fn apply_defining_uses(
91+
&mut self,
92+
opaque_types: &[(OpaqueTypeKey<'tcx>, OpaqueHiddenType<'tcx>)],
93+
) {
94+
let tcx = self.tcx;
95+
for &(key, hidden_type) in opaque_types {
96+
let Some(&expected) =
97+
self.typeck_results.borrow_mut().concrete_opaque_types.get(&key.def_id)
98+
else {
99+
let guar =
100+
tcx.dcx().span_err(hidden_type.span, "non-defining use in the defining scope");
101+
self.typeck_results
102+
.borrow_mut()
103+
.concrete_opaque_types
104+
.insert(key.def_id, OpaqueHiddenType::new_error(tcx, guar));
105+
self.set_tainted_by_errors(guar);
106+
continue;
107+
};
108+
109+
let expected = EarlyBinder::bind(expected.ty).instantiate(tcx, key.args);
110+
self.demand_eqtype(hidden_type.span, expected, hidden_type.ty);
111+
}
112+
}
113+
}

compiler/rustc_hir_typeck/src/writeback.rs

+26-17
Original file line numberDiff line numberDiff line change
@@ -534,29 +534,31 @@ impl<'cx, 'tcx> WritebackCx<'cx, 'tcx> {
534534
}
535535
}
536536

537+
fn visit_opaque_types_next(&mut self) {
538+
let fcx_typeck_results = self.fcx.typeck_results.borrow();
539+
assert_eq!(fcx_typeck_results.hir_owner, self.typeck_results.hir_owner);
540+
for (&def_id, &hidden_type) in &fcx_typeck_results.concrete_opaque_types {
541+
assert!(!hidden_type.has_infer());
542+
self.typeck_results.concrete_opaque_types.insert(def_id, hidden_type);
543+
}
544+
}
545+
537546
#[instrument(skip(self), level = "debug")]
538547
fn visit_opaque_types(&mut self) {
548+
if self.fcx.next_trait_solver() {
549+
return self.visit_opaque_types_next();
550+
}
551+
539552
let tcx = self.tcx();
540-
// We clone the opaques instead of stealing them here as they are still used for
541-
// normalization in the next generation trait solver.
542-
//
543-
// FIXME(-Znext-solver): Opaque types defined after this would simply get dropped
544-
// at the end of typeck. While this seems unlikely to happen in practice this
545-
// should still get fixed. Either by preventing writeback from defining new opaque
546-
// types or by using this function at the end of writeback and running it as a
547-
// fixpoint.
548-
let opaque_types = self.fcx.infcx.clone_opaque_types();
553+
let opaque_types = self.fcx.infcx.take_opaque_types();
549554
for (opaque_type_key, hidden_type) in opaque_types {
550555
let hidden_type = self.resolve(hidden_type, &hidden_type.span);
551556
let opaque_type_key = self.resolve(opaque_type_key, &hidden_type.span);
552-
553-
if !self.fcx.next_trait_solver() {
554-
if let ty::Alias(ty::Opaque, alias_ty) = hidden_type.ty.kind()
555-
&& alias_ty.def_id == opaque_type_key.def_id.to_def_id()
556-
&& alias_ty.args == opaque_type_key.args
557-
{
558-
continue;
559-
}
557+
if let ty::Alias(ty::Opaque, alias_ty) = hidden_type.ty.kind()
558+
&& alias_ty.def_id == opaque_type_key.def_id.to_def_id()
559+
&& alias_ty.args == opaque_type_key.args
560+
{
561+
continue;
560562
}
561563

562564
if let Err(err) = check_opaque_type_parameter_valid(
@@ -571,6 +573,13 @@ impl<'cx, 'tcx> WritebackCx<'cx, 'tcx> {
571573
);
572574
}
573575

576+
if hidden_type.has_non_region_infer() {
577+
let guar = self.fcx.dcx().span_err(hidden_type.span, "hidden_type has infer");
578+
self.typeck_results
579+
.concrete_opaque_types
580+
.insert(opaque_type_key.def_id, OpaqueHiddenType::new_error(tcx, guar));
581+
continue;
582+
}
574583
let hidden_type = hidden_type.remap_generic_params_to_declaration_params(
575584
opaque_type_key,
576585
tcx,

compiler/rustc_next_trait_solver/src/solve/eval_ctxt/mod.rs

-20
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,6 @@ use std::ops::ControlFlow;
44
#[cfg(feature = "nightly")]
55
use rustc_macros::HashStable_NoContext;
66
use rustc_type_ir::data_structures::{HashMap, HashSet, ensure_sufficient_stack};
7-
use rustc_type_ir::fast_reject::DeepRejectCtxt;
87
use rustc_type_ir::inherent::*;
98
use rustc_type_ir::relate::Relate;
109
use rustc_type_ir::relate::solver_relating::RelateExt;
@@ -1072,25 +1071,6 @@ where
10721071
self.add_goals(GoalSource::AliasWellFormed, goals);
10731072
}
10741073

1075-
// Do something for each opaque/hidden pair defined with `def_id` in the
1076-
// current inference context.
1077-
pub(super) fn probe_existing_opaque_ty(
1078-
&mut self,
1079-
key: ty::OpaqueTypeKey<I>,
1080-
) -> Option<(ty::OpaqueTypeKey<I>, I::Ty)> {
1081-
let mut matching = self.delegate.clone_opaque_types_lookup_table().into_iter().filter(
1082-
|(candidate_key, _)| {
1083-
candidate_key.def_id == key.def_id
1084-
&& DeepRejectCtxt::relate_rigid_rigid(self.cx())
1085-
.args_may_unify(candidate_key.args, key.args)
1086-
},
1087-
);
1088-
let first = matching.next();
1089-
let second = matching.next();
1090-
assert_eq!(second, None);
1091-
first
1092-
}
1093-
10941074
// Try to evaluate a const, or return `None` if the const is too generic.
10951075
// This doesn't mean the const isn't evaluatable, though, and should be treated
10961076
// as an ambiguity rather than no-solution.

compiler/rustc_next_trait_solver/src/solve/normalizes_to/opaque_types.rs

+19-88
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,12 @@
11
//! Computes a normalizes-to (projection) goal for opaque types. This goal
22
//! behaves differently depending on the current `TypingMode`.
33
4-
use rustc_index::bit_set::GrowableBitSet;
54
use rustc_type_ir::inherent::*;
65
use rustc_type_ir::solve::GoalSource;
7-
use rustc_type_ir::{self as ty, Interner, TypingMode, fold_regions};
6+
use rustc_type_ir::{self as ty, GenericArgKind, Interner, TypingMode, fold_regions};
87

98
use crate::delegate::SolverDelegate;
10-
use crate::solve::{Certainty, EvalCtxt, Goal, NoSolution, QueryResult, inspect};
9+
use crate::solve::{Certainty, EvalCtxt, Goal, QueryResult};
1110

1211
impl<D, I> EvalCtxt<'_, D>
1312
where
@@ -49,54 +48,27 @@ where
4948
return self.evaluate_added_goals_and_make_canonical_response(Certainty::Yes);
5049
};
5150

52-
// FIXME: This may have issues when the args contain aliases...
53-
match uses_unique_placeholders_ignoring_regions(self.cx(), opaque_ty.args) {
54-
Err(NotUniqueParam::NotParam(param)) if param.is_non_region_infer() => {
55-
return self.evaluate_added_goals_and_make_canonical_response(
56-
Certainty::AMBIGUOUS,
57-
);
58-
}
59-
Err(_) => {
60-
return Err(NoSolution);
61-
}
62-
Ok(()) => {}
63-
}
64-
// Prefer opaques registered already.
65-
let opaque_type_key = ty::OpaqueTypeKey { def_id, args: opaque_ty.args };
66-
// FIXME: This also unifies the previous hidden type with the expected.
67-
//
68-
// If that fails, we insert `expected` as a new hidden type instead of
69-
// eagerly emitting an error.
70-
let existing = self.probe_existing_opaque_ty(opaque_type_key);
71-
if let Some((candidate_key, candidate_ty)) = existing {
72-
return self
73-
.probe(|result| inspect::ProbeKind::OpaqueTypeStorageLookup {
74-
result: *result,
75-
})
76-
.enter(|ecx| {
77-
for (a, b) in std::iter::zip(
78-
candidate_key.args.iter(),
79-
opaque_type_key.args.iter(),
80-
) {
81-
ecx.eq(goal.param_env, a, b)?;
82-
}
83-
ecx.eq(goal.param_env, candidate_ty, expected)?;
84-
ecx.add_item_bounds_for_hidden_type(
85-
def_id.into(),
86-
candidate_key.args,
87-
goal.param_env,
88-
candidate_ty,
89-
);
90-
ecx.evaluate_added_goals_and_make_canonical_response(Certainty::Yes)
91-
});
51+
// We structurally normalize the args to
52+
let normalized_args =
53+
cx.mk_args_from_iter(opaque_ty.args.iter().map(|arg| match arg.kind() {
54+
GenericArgKind::Lifetime(lt) => Ok(lt.into()),
55+
GenericArgKind::Type(ty) => {
56+
self.structurally_normalize_ty(goal.param_env, ty).map(Into::into)
57+
}
58+
GenericArgKind::Const(ct) => {
59+
self.structurally_normalize_const(goal.param_env, ct).map(Into::into)
60+
}
61+
}))?;
62+
63+
let opaque_type_key = ty::OpaqueTypeKey { def_id, args: normalized_args };
64+
if let Some(prev) = self.register_hidden_type_in_storage(opaque_type_key, expected)
65+
{
66+
self.eq(goal.param_env, expected, prev)?;
9267
}
9368

94-
// Otherwise, define a new opaque type
95-
let prev = self.register_hidden_type_in_storage(opaque_type_key, expected);
96-
assert_eq!(prev, None);
9769
self.add_item_bounds_for_hidden_type(
9870
def_id.into(),
99-
opaque_ty.args,
71+
normalized_args,
10072
goal.param_env,
10173
expected,
10274
);
@@ -168,44 +140,3 @@ where
168140
}
169141
}
170142
}
171-
172-
/// Checks whether each generic argument is simply a unique generic placeholder.
173-
///
174-
/// FIXME: Interner argument is needed to constrain the `I` parameter.
175-
fn uses_unique_placeholders_ignoring_regions<I: Interner>(
176-
_cx: I,
177-
args: I::GenericArgs,
178-
) -> Result<(), NotUniqueParam<I>> {
179-
let mut seen = GrowableBitSet::default();
180-
for arg in args.iter() {
181-
match arg.kind() {
182-
// Ignore regions, since we can't resolve those in a canonicalized
183-
// query in the trait solver.
184-
ty::GenericArgKind::Lifetime(_) => {}
185-
ty::GenericArgKind::Type(t) => match t.kind() {
186-
ty::Placeholder(p) => {
187-
if !seen.insert(p.var()) {
188-
return Err(NotUniqueParam::DuplicateParam(t.into()));
189-
}
190-
}
191-
_ => return Err(NotUniqueParam::NotParam(t.into())),
192-
},
193-
ty::GenericArgKind::Const(c) => match c.kind() {
194-
ty::ConstKind::Placeholder(p) => {
195-
if !seen.insert(p.var()) {
196-
return Err(NotUniqueParam::DuplicateParam(c.into()));
197-
}
198-
}
199-
_ => return Err(NotUniqueParam::NotParam(c.into())),
200-
},
201-
}
202-
}
203-
204-
Ok(())
205-
}
206-
207-
// FIXME: This should check for dupes and non-params first, then infer vars.
208-
enum NotUniqueParam<I: Interner> {
209-
DuplicateParam(I::GenericArg),
210-
NotParam(I::GenericArg),
211-
}

compiler/rustc_session/src/config.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -997,7 +997,7 @@ pub struct NextSolverConfig {
997997
pub coherence: bool = true,
998998
/// Whether the new trait solver should be enabled everywhere.
999999
/// This is only `true` if `coherence` is also enabled.
1000-
pub globally: bool = false,
1000+
pub globally: bool = true,
10011001
}
10021002

10031003
#[derive(Clone)]

0 commit comments

Comments
 (0)