Skip to content

Commit

Permalink
Rollup merge of #112399 - compiler-errors:closure-substs-root-univers…
Browse files Browse the repository at this point in the history
…e, 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```
  • Loading branch information
Dylan-DPC committed Jun 16, 2023
2 parents c563296 + e3b499f commit b41db84
Show file tree
Hide file tree
Showing 3 changed files with 13 additions and 2 deletions.
4 changes: 2 additions & 2 deletions compiler/rustc_hir_typeck/src/closure.rs
Original file line number Diff line number Diff line change
Expand Up @@ -98,7 +98,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
self.tcx.typeck_root_def_id(expr_def_id.to_def_id()),
);

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

// Create a type variable (for now) to represent the closure kind.
// It will be unified during the upvar inference phase (`upvar.rs`)
None => self.next_ty_var(TypeVariableOrigin {
None => self.next_root_ty_var(TypeVariableOrigin {
// FIXME(eddyb) distinguish closure kind inference variables from the rest.
kind: TypeVariableOriginKind::ClosureSynthetic,
span: expr_span,
Expand Down
4 changes: 4 additions & 0 deletions compiler/rustc_hir_typeck/src/fn_ctxt/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -189,6 +189,10 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
pub fn errors_reported_since_creation(&self) -> bool {
self.tcx.sess.err_count() > self.err_count_on_creation
}

pub fn next_root_ty_var(&self, origin: TypeVariableOrigin) -> Ty<'tcx> {
self.tcx.mk_ty_var(self.next_ty_var_id_in_universe(origin, ty::UniverseIndex::ROOT))
}
}

impl<'a, 'tcx> Deref for FnCtxt<'a, 'tcx> {
Expand Down
7 changes: 7 additions & 0 deletions tests/ui/traits/new-solver/closure-substs-ambiguity.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
// compile-flags: -Ztrait-solver=next
// check-pass

fn main() {
let mut x: Vec<_> = vec![];
x.extend(Some(1i32).into_iter().map(|x| x));
}

0 comments on commit b41db84

Please sign in to comment.