Skip to content

Commit b41db84

Browse files
authored
Rollup merge of rust-lang#112399 - compiler-errors:closure-substs-root-universe, r=lcnr
Instantiate closure synthetic substs in root universe In the UI test example, we end up generalizing an associated type (something like `<Map<Option<i32>, [closure upvars=?0]> as IntoIterator>::Item` generalizes into `<Map<Option<i32>, [closure upvars=?1]> as IntoIterator>::Item`) then assigning it to itself, emitting an alias-relate goal. This trivially holds via one of the normalizes-to candidates, instead of relating substs, so when closure analysis eventually sets `?0` to the actual upvars, `?1` never gets constrained. This ends up being reported as an ambiguity error during writeback. Instead, we can take advantage of the fact that we *know* the closure substs live in the root universe. This will prevent them being generalized, since they always can be named, and the alias-relate above never gets emitted at all. We can probably do this to a handful of other `next_ty_var` calls in typeck for variables that are clearly associated with the body of the program, but I wanted to limit this for now. Eventually, if we end up representing universes more faithfully like a tree or whatever, we can remove this and turn it back to just a call to `next_ty_var`. Note: This is incredibly order-dependent -- we need to be assigning a type variable that was created *before* the closure substs, and we also need to actually have an unnormalized type at the time of the assignment. This currently seems easiest to trigger during call argument analysis just due to the fact that we instantiate the call's substs, normalize, THEN check args. r? ```@lcnr```
2 parents c563296 + e3b499f commit b41db84

File tree

3 files changed

+13
-2
lines changed

3 files changed

+13
-2
lines changed

compiler/rustc_hir_typeck/src/closure.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -98,7 +98,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
9898
self.tcx.typeck_root_def_id(expr_def_id.to_def_id()),
9999
);
100100

101-
let tupled_upvars_ty = self.next_ty_var(TypeVariableOrigin {
101+
let tupled_upvars_ty = self.next_root_ty_var(TypeVariableOrigin {
102102
kind: TypeVariableOriginKind::ClosureSynthetic,
103103
span: self.tcx.def_span(expr_def_id),
104104
});
@@ -143,7 +143,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
143143

144144
// Create a type variable (for now) to represent the closure kind.
145145
// It will be unified during the upvar inference phase (`upvar.rs`)
146-
None => self.next_ty_var(TypeVariableOrigin {
146+
None => self.next_root_ty_var(TypeVariableOrigin {
147147
// FIXME(eddyb) distinguish closure kind inference variables from the rest.
148148
kind: TypeVariableOriginKind::ClosureSynthetic,
149149
span: expr_span,

compiler/rustc_hir_typeck/src/fn_ctxt/mod.rs

+4
Original file line numberDiff line numberDiff line change
@@ -189,6 +189,10 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
189189
pub fn errors_reported_since_creation(&self) -> bool {
190190
self.tcx.sess.err_count() > self.err_count_on_creation
191191
}
192+
193+
pub fn next_root_ty_var(&self, origin: TypeVariableOrigin) -> Ty<'tcx> {
194+
self.tcx.mk_ty_var(self.next_ty_var_id_in_universe(origin, ty::UniverseIndex::ROOT))
195+
}
192196
}
193197

194198
impl<'a, 'tcx> Deref for FnCtxt<'a, 'tcx> {
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
// compile-flags: -Ztrait-solver=next
2+
// check-pass
3+
4+
fn main() {
5+
let mut x: Vec<_> = vec![];
6+
x.extend(Some(1i32).into_iter().map(|x| x));
7+
}

0 commit comments

Comments
 (0)