Rollup merge of #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```
This commit is contained in:
commit
b41db841e8
3 changed files with 13 additions and 2 deletions
|
@ -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),
|
||||
});
|
||||
|
@ -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,
|
||||
|
|
|
@ -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> {
|
||||
|
|
7
tests/ui/traits/new-solver/closure-substs-ambiguity.rs
Normal file
7
tests/ui/traits/new-solver/closure-substs-ambiguity.rs
Normal file
|
@ -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));
|
||||
}
|
Loading…
Add table
Reference in a new issue