Skip to content

Commit d5643be

Browse files
authored
Rollup merge of #61488 - matthewjasper:fix-nll-typeck-ices, r=pnkfelix
Fix NLL typeck ICEs * Don't ICE when a type containing a region is constrained by nothing * Don't ICE trying to normalize a type in a `ParamEnv` containing global bounds. To explain what was happening in the `issue-61311-normalize.rs` case: * When borrow checking the `the_fn` in the last `impl` we would try to normalize `Self::Proj` (`<Unit as HasProjFn>::Proj`). * We would find the `impl` that we're checking and and check its `where` clause. * This would need us to check `<Box<dyn Obj + 'static> as HasProj>::Proj: Bound` * We find two possible implementations, the blanket impl and the bound in our `ParamEnv`. * The bound in our `ParamEnv` was canonicalized, so we don't see it as a global bound. As such we prefer it to the `impl`. * This means that we cannot normalize `<Box<dyn Obj + 'static> as HasProj>::Proj` to `Unit`. * The `<Box<dyn Obj + 'static> as HasProj>::Proj: Bound` bound, which looks like it should be in our `ParamEnv` has been normalized to `Unit: Bound`. * We fail to prove `<Box<dyn Obj + 'static> as HasProj>::Proj: Bound`. * We ICE, since we believe typeck have errored. Closes #61311 Closes #61315 Closes #61320 r? @pnkfelix cc @nikomatsakis
2 parents 98176fc + 794239d commit d5643be

File tree

6 files changed

+222
-4
lines changed

6 files changed

+222
-4
lines changed

src/librustc/infer/canonical/canonicalizer.rs

+7-3
Original file line numberDiff line numberDiff line change
@@ -115,13 +115,17 @@ impl<'cx, 'gcx, 'tcx> InferCtxt<'cx, 'gcx, 'tcx> {
115115

116116
/// A hacky variant of `canonicalize_query` that does not
117117
/// canonicalize `'static`. Unfortunately, the existing leak
118-
/// check treaks `'static` differently in some cases (see also
118+
/// check treats `'static` differently in some cases (see also
119119
/// #33684), so if we are performing an operation that may need to
120120
/// prove "leak-check" related things, we leave `'static`
121121
/// alone.
122+
///
123+
/// `'static` is also special cased when winnowing candidates when
124+
/// selecting implementation candidates, so we also have to leave `'static`
125+
/// alone for queries that do selection.
122126
//
123-
// FIXME(#48536): once we have universes, we can remove this and just use
124-
// `canonicalize_query`.
127+
// FIXME(#48536): once the above issues are resolved, we can remove this
128+
// and just use `canonicalize_query`.
125129
pub fn canonicalize_hr_query_hack<V>(
126130
&self,
127131
value: &V,

src/librustc/traits/query/normalize.rs

+3-1
Original file line numberDiff line numberDiff line change
@@ -145,7 +145,9 @@ impl<'cx, 'gcx, 'tcx> TypeFolder<'gcx, 'tcx> for QueryNormalizer<'cx, 'gcx, 'tcx
145145
let gcx = self.infcx.tcx.global_tcx();
146146

147147
let mut orig_values = OriginalQueryValues::default();
148-
let c_data = self.infcx.canonicalize_query(
148+
// HACK(matthewjasper) `'static` is special-cased in selection,
149+
// so we cannot canonicalize it.
150+
let c_data = self.infcx.canonicalize_hr_query_hack(
149151
&self.param_env.and(*data), &mut orig_values);
150152
debug!("QueryNormalizer: c_data = {:#?}", c_data);
151153
debug!("QueryNormalizer: orig_values = {:#?}", orig_values);

src/librustc_mir/borrow_check/nll/type_check/free_region_relations.rs

+7
Original file line numberDiff line numberDiff line change
@@ -334,6 +334,13 @@ impl UniversalRegionRelationsBuilder<'cx, 'gcx, 'tcx> {
334334

335335
match outlives_bound {
336336
OutlivesBound::RegionSubRegion(r1, r2) => {
337+
// `where Type:` is lowered to `where Type: 'empty` so that
338+
// we check `Type` is well formed, but there's no use for
339+
// this bound here.
340+
if let ty::ReEmpty = r1 {
341+
return;
342+
}
343+
337344
// The bound says that `r1 <= r2`; we store `r2: r1`.
338345
let r1 = self.universal_regions.to_region_vid(r1);
339346
let r2 = self.universal_regions.to_region_vid(r2);
+11
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
// Regression test for #61315
2+
//
3+
// `dyn T:` is lowered to `dyn T: ReEmpty` - check that we don't ICE in NLL for
4+
// the unexpected region.
5+
6+
// compile-pass
7+
8+
trait T {}
9+
fn f() where dyn T: {}
10+
11+
fn main() {}
+34
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
// Regression test for #61311
2+
// We would ICE after failing to normalize `Self::Proj` in the `impl` below.
3+
4+
// compile-pass
5+
6+
pub struct Unit;
7+
trait Obj {}
8+
9+
trait Bound {}
10+
impl Bound for Unit {}
11+
12+
pub trait HasProj {
13+
type Proj;
14+
}
15+
16+
impl<T> HasProj for T {
17+
type Proj = Unit;
18+
}
19+
20+
trait HasProjFn {
21+
type Proj;
22+
fn the_fn(_: Self::Proj);
23+
}
24+
25+
impl HasProjFn for Unit
26+
where
27+
Box<dyn Obj + 'static>: HasProj,
28+
<Box<dyn Obj + 'static> as HasProj>::Proj: Bound,
29+
{
30+
type Proj = Unit;
31+
fn the_fn(_: Self::Proj) {}
32+
}
33+
34+
fn main() {}
+160
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,160 @@
1+
// Regression test for #61320
2+
// This is the same issue as #61311, just a larger test case.
3+
4+
// compile-pass
5+
6+
pub struct AndThen<A, B, F>
7+
where
8+
A: Future,
9+
B: IntoFuture,
10+
{
11+
state: (A, B::Future, F),
12+
}
13+
14+
pub struct FutureResult<T, E> {
15+
inner: Option<Result<T, E>>,
16+
}
17+
18+
impl<T, E> Future for FutureResult<T, E> {
19+
type Item = T;
20+
type Error = E;
21+
22+
fn poll(&mut self) -> Poll<T, E> {
23+
unimplemented!()
24+
}
25+
}
26+
27+
pub type Poll<T, E> = Result<T, E>;
28+
29+
impl<A, B, F> Future for AndThen<A, B, F>
30+
where
31+
A: Future,
32+
B: IntoFuture<Error = A::Error>,
33+
F: FnOnce(A::Item) -> B,
34+
{
35+
type Item = B::Item;
36+
type Error = B::Error;
37+
38+
fn poll(&mut self) -> Poll<B::Item, B::Error> {
39+
unimplemented!()
40+
}
41+
}
42+
43+
pub trait Future {
44+
type Item;
45+
46+
type Error;
47+
48+
fn poll(&mut self) -> Poll<Self::Item, Self::Error>;
49+
50+
fn and_then<F, B>(self, f: F) -> AndThen<Self, B, F>
51+
where
52+
F: FnOnce(Self::Item) -> B,
53+
B: IntoFuture<Error = Self::Error>,
54+
Self: Sized,
55+
{
56+
unimplemented!()
57+
}
58+
}
59+
60+
pub trait IntoFuture {
61+
/// The future that this type can be converted into.
62+
type Future: Future<Item = Self::Item, Error = Self::Error>;
63+
64+
/// The item that the future may resolve with.
65+
type Item;
66+
/// The error that the future may resolve with.
67+
type Error;
68+
69+
/// Consumes this object and produces a future.
70+
fn into_future(self) -> Self::Future;
71+
}
72+
73+
impl<F: Future> IntoFuture for F {
74+
type Future = F;
75+
type Item = F::Item;
76+
type Error = F::Error;
77+
78+
fn into_future(self) -> F {
79+
self
80+
}
81+
}
82+
83+
impl<F: ?Sized + Future> Future for ::std::boxed::Box<F> {
84+
type Item = F::Item;
85+
type Error = F::Error;
86+
87+
fn poll(&mut self) -> Poll<Self::Item, Self::Error> {
88+
(**self).poll()
89+
}
90+
}
91+
92+
impl<T, E> IntoFuture for Result<T, E> {
93+
type Future = FutureResult<T, E>;
94+
type Item = T;
95+
type Error = E;
96+
97+
fn into_future(self) -> FutureResult<T, E> {
98+
unimplemented!()
99+
}
100+
}
101+
102+
struct Request<T>(T);
103+
104+
trait RequestContext {}
105+
impl<T> RequestContext for T {}
106+
struct NoContext;
107+
impl AsRef<NoContext> for NoContext {
108+
fn as_ref(&self) -> &Self {
109+
&NoContext
110+
}
111+
}
112+
113+
type BoxedError = Box<dyn std::error::Error + Send + Sync>;
114+
type DefaultFuture<T, E> = Box<dyn Future<Item = T, Error = E> + Send>;
115+
116+
trait Guard: Sized {
117+
type Result: IntoFuture<Item = Self, Error = BoxedError>;
118+
fn from_request(request: &Request<()>) -> Self::Result;
119+
}
120+
121+
trait FromRequest: Sized {
122+
type Context;
123+
type Future: Future<Item = Self, Error = BoxedError> + Send;
124+
fn from_request(request: Request<()>) -> Self::Future;
125+
}
126+
127+
struct MyGuard;
128+
impl Guard for MyGuard {
129+
type Result = Result<Self, BoxedError>;
130+
fn from_request(_request: &Request<()>) -> Self::Result {
131+
Ok(MyGuard)
132+
}
133+
}
134+
135+
struct Generic<I> {
136+
_inner: I,
137+
}
138+
139+
impl<I> FromRequest for Generic<I>
140+
where
141+
MyGuard: Guard,
142+
<MyGuard as Guard>::Result: IntoFuture<Item = MyGuard, Error = BoxedError>,
143+
<<MyGuard as Guard>::Result as IntoFuture>::Future: Send,
144+
I: FromRequest<Context = NoContext>,
145+
{
146+
type Future = DefaultFuture<Self, BoxedError>;
147+
type Context = NoContext;
148+
fn from_request(headers: Request<()>) -> DefaultFuture<Self, BoxedError> {
149+
let _future = <MyGuard as Guard>::from_request(&headers)
150+
.into_future()
151+
.and_then(move |_| {
152+
<I as FromRequest>::from_request(headers)
153+
.into_future()
154+
.and_then(move |fld_inner| Ok(Generic { _inner: fld_inner }).into_future())
155+
});
156+
panic!();
157+
}
158+
}
159+
160+
fn main() {}

0 commit comments

Comments
 (0)