Skip to content

Commit cd56e25

Browse files
committed
Auto merge of #83870 - jackh726:binder-refactor-fix, r=nikomatsakis
Don't concatenate binders across types Partially addresses #83737 There's actually two issues that I uncovered in #83737. The first is that we are concatenating bound vars across types, i.e. in ``` F: Fn(&()) -> &mut (dyn Future<Output = ()> + Unpin) ``` the bound vars on `Future` get set as `for<anon>` since those are the binders on `Fn(&()`. This is obviously wrong, since we should only concatenate directly nested trait refs. This is solved here by introducing a new `TraitRefBoundary` scope, that we put around the "syntactical" trait refs and basically don't allow concatenation across. Now, this alone *shouldn't* be a super terrible problem. At least not until you consider the other issue, which is a much more elusive and harder to design a "perfect" fix. A repro can be seen in: ``` use core::future::Future; async fn handle<F>(slf: &F) where F: Fn(&()) -> &mut (dyn for<'a> Future<Output = ()> + Unpin), { (slf)(&()).await; } ``` Notice the `for<'a>` around `Future`. Here, `'a` is unused, so the `for<'a>` Binder gets changed to a `for<>` Binder in the generator witness, but the "local decl" still has it. This has heavy intersections with region anonymization and erasing. Luckily, it's not *super* common to find this unique set of circumstances. It only became apparently because of the first issue mentioned here. However, this *is* still a problem, so I'm leaving #83737 open. r? `@nikomatsakis`
2 parents 619d19c + c1dc0b7 commit cd56e25

File tree

4 files changed

+237
-86
lines changed

4 files changed

+237
-86
lines changed

compiler/rustc_middle/src/ty/print/pretty.rs

+87-22
Original file line numberDiff line numberDiff line change
@@ -1804,29 +1804,94 @@ impl<F: fmt::Write> FmtPrinter<'_, 'tcx, F> {
18041804
define_scoped_cx!(self);
18051805

18061806
let mut region_index = self.region_index;
1807-
let new_value = self.tcx.replace_late_bound_regions(value.clone(), |br| {
1808-
let _ = start_or_continue(&mut self, "for<", ", ");
1809-
let kind = match br.kind {
1810-
ty::BrNamed(_, name) => {
1811-
let _ = write!(self, "{}", name);
1812-
br.kind
1813-
}
1814-
ty::BrAnon(_) | ty::BrEnv => {
1815-
let name = loop {
1816-
let name = name_by_region_index(region_index);
1817-
region_index += 1;
1818-
if !self.used_region_names.contains(&name) {
1819-
break name;
1820-
}
1821-
};
1822-
let _ = write!(self, "{}", name);
1823-
ty::BrNamed(DefId::local(CRATE_DEF_INDEX), name)
1807+
// If we want to print verbosly, then print *all* binders, even if they
1808+
// aren't named. Eventually, we might just want this as the default, but
1809+
// this is not *quite* right and changes the ordering of some output
1810+
// anyways.
1811+
let new_value = if self.tcx().sess.verbose() {
1812+
// anon index + 1 (BrEnv takes 0) -> name
1813+
let mut region_map: BTreeMap<u32, Symbol> = BTreeMap::default();
1814+
let bound_vars = value.bound_vars();
1815+
for var in bound_vars {
1816+
match var {
1817+
ty::BoundVariableKind::Region(ty::BrNamed(_, name)) => {
1818+
let _ = start_or_continue(&mut self, "for<", ", ");
1819+
let _ = write!(self, "{}", name);
1820+
}
1821+
ty::BoundVariableKind::Region(ty::BrAnon(i)) => {
1822+
let _ = start_or_continue(&mut self, "for<", ", ");
1823+
let name = loop {
1824+
let name = name_by_region_index(region_index);
1825+
region_index += 1;
1826+
if !self.used_region_names.contains(&name) {
1827+
break name;
1828+
}
1829+
};
1830+
let _ = write!(self, "{}", name);
1831+
region_map.insert(i + 1, name);
1832+
}
1833+
ty::BoundVariableKind::Region(ty::BrEnv) => {
1834+
let _ = start_or_continue(&mut self, "for<", ", ");
1835+
let name = loop {
1836+
let name = name_by_region_index(region_index);
1837+
region_index += 1;
1838+
if !self.used_region_names.contains(&name) {
1839+
break name;
1840+
}
1841+
};
1842+
let _ = write!(self, "{}", name);
1843+
region_map.insert(0, name);
1844+
}
1845+
_ => continue,
18241846
}
1825-
};
1826-
self.tcx
1827-
.mk_region(ty::ReLateBound(ty::INNERMOST, ty::BoundRegion { var: br.var, kind }))
1828-
});
1829-
start_or_continue(&mut self, "", "> ")?;
1847+
}
1848+
start_or_continue(&mut self, "", "> ")?;
1849+
1850+
self.tcx.replace_late_bound_regions(value.clone(), |br| {
1851+
let kind = match br.kind {
1852+
ty::BrNamed(_, _) => br.kind,
1853+
ty::BrAnon(i) => {
1854+
let name = region_map[&(i + 1)];
1855+
ty::BrNamed(DefId::local(CRATE_DEF_INDEX), name)
1856+
}
1857+
ty::BrEnv => {
1858+
let name = region_map[&0];
1859+
ty::BrNamed(DefId::local(CRATE_DEF_INDEX), name)
1860+
}
1861+
};
1862+
self.tcx.mk_region(ty::ReLateBound(
1863+
ty::INNERMOST,
1864+
ty::BoundRegion { var: br.var, kind },
1865+
))
1866+
})
1867+
} else {
1868+
let new_value = self.tcx.replace_late_bound_regions(value.clone(), |br| {
1869+
let _ = start_or_continue(&mut self, "for<", ", ");
1870+
let kind = match br.kind {
1871+
ty::BrNamed(_, name) => {
1872+
let _ = write!(self, "{}", name);
1873+
br.kind
1874+
}
1875+
ty::BrAnon(_) | ty::BrEnv => {
1876+
let name = loop {
1877+
let name = name_by_region_index(region_index);
1878+
region_index += 1;
1879+
if !self.used_region_names.contains(&name) {
1880+
break name;
1881+
}
1882+
};
1883+
let _ = write!(self, "{}", name);
1884+
ty::BrNamed(DefId::local(CRATE_DEF_INDEX), name)
1885+
}
1886+
};
1887+
self.tcx.mk_region(ty::ReLateBound(
1888+
ty::INNERMOST,
1889+
ty::BoundRegion { var: br.var, kind },
1890+
))
1891+
});
1892+
start_or_continue(&mut self, "", "> ")?;
1893+
new_value
1894+
};
18301895

18311896
self.binder_depth += 1;
18321897
self.region_index = region_index;

compiler/rustc_mir/src/transform/generator.rs

+4-3
Original file line numberDiff line numberDiff line change
@@ -751,9 +751,10 @@ fn sanitize_witness<'tcx>(
751751
span_bug!(
752752
body.span,
753753
"Broken MIR: generator contains type {} in MIR, \
754-
but typeck only knows about {}",
755-
decl.ty,
756-
witness,
754+
but typeck only knows about {} and {:?}",
755+
decl_ty,
756+
allowed,
757+
allowed_upvars
757758
);
758759
}
759760
}

0 commit comments

Comments
 (0)