Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fall back when relating two opaques by substs in MIR typeck #100092

Merged
merged 2 commits into from
Aug 30, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
58 changes: 34 additions & 24 deletions compiler/rustc_infer/src/infer/nll_relate/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -396,6 +396,32 @@ where

generalizer.relate(value, value)
}

fn relate_opaques(&mut self, a: Ty<'tcx>, b: Ty<'tcx>) -> RelateResult<'tcx, Ty<'tcx>> {
let (a, b) = if self.a_is_expected() { (a, b) } else { (b, a) };
let mut generalize = |ty, ty_is_expected| {
let var = self.infcx.next_ty_var_id_in_universe(
TypeVariableOrigin {
kind: TypeVariableOriginKind::MiscVariable,
span: self.delegate.span(),
},
ty::UniverseIndex::ROOT,
);
if ty_is_expected {
self.relate_ty_var((ty, var))
} else {
self.relate_ty_var((var, ty))
}
};
let (a, b) = match (a.kind(), b.kind()) {
(&ty::Opaque(..), _) => (a, generalize(b, false)?),
(_, &ty::Opaque(..)) => (generalize(a, true)?, b),
_ => unreachable!(),
};
self.delegate.register_opaque_type(a, b, true)?;
trace!(a = ?a.kind(), b = ?b.kind(), "opaque type instantiated");
Ok(a)
}
}

/// When we instantiate an inference variable with a value in
Expand Down Expand Up @@ -572,32 +598,16 @@ where
(&ty::Infer(ty::TyVar(vid)), _) => self.relate_ty_var((vid, b)),

(&ty::Opaque(a_def_id, _), &ty::Opaque(b_def_id, _)) if a_def_id == b_def_id => {
self.infcx.super_combine_tys(self, a, b)
infcx.commit_if_ok(|_| infcx.super_combine_tys(self, a, b)).or_else(|err| {
self.tcx().sess.delay_span_bug(
self.delegate.span(),
"failure to relate an opaque to itself should result in an error later on",
);
if a_def_id.is_local() { self.relate_opaques(a, b) } else { Err(err) }
})
}
(&ty::Opaque(did, ..), _) | (_, &ty::Opaque(did, ..)) if did.is_local() => {
let (a, b) = if self.a_is_expected() { (a, b) } else { (b, a) };
let mut generalize = |ty, ty_is_expected| {
let var = infcx.next_ty_var_id_in_universe(
TypeVariableOrigin {
kind: TypeVariableOriginKind::MiscVariable,
span: self.delegate.span(),
},
ty::UniverseIndex::ROOT,
);
if ty_is_expected {
self.relate_ty_var((ty, var))
} else {
self.relate_ty_var((var, ty))
}
};
let (a, b) = match (a.kind(), b.kind()) {
(&ty::Opaque(..), _) => (a, generalize(b, false)?),
(_, &ty::Opaque(..)) => (generalize(a, true)?, b),
_ => unreachable!(),
};
self.delegate.register_opaque_type(a, b, true)?;
trace!(a = ?a.kind(), b = ?b.kind(), "opaque type instantiated");
Ok(a)
self.relate_opaques(a, b)
}

(&ty::Projection(projection_ty), _)
Expand Down
8 changes: 8 additions & 0 deletions src/test/ui/impl-trait/issue-100075-2.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
fn opaque<T>(t: T) -> impl Sized {
//~^ ERROR cannot resolve opaque type
//~| WARNING function cannot return without recursing
opaque(Some(t))
}

#[allow(dead_code)]
fn main() {}
24 changes: 24 additions & 0 deletions src/test/ui/impl-trait/issue-100075-2.stderr
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
warning: function cannot return without recursing
--> $DIR/issue-100075-2.rs:1:1
|
LL | fn opaque<T>(t: T) -> impl Sized {
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ cannot return without recursing
...
LL | opaque(Some(t))
| --------------- recursive call site
|
= note: `#[warn(unconditional_recursion)]` on by default
= help: a `loop` may express intention better if this is on purpose

error[E0720]: cannot resolve opaque type
--> $DIR/issue-100075-2.rs:1:23
|
LL | fn opaque<T>(t: T) -> impl Sized {
| ^^^^^^^^^^ recursive opaque type
...
LL | opaque(Some(t))
| --------------- returning here with type `impl Sized`

error: aborting due to previous error; 1 warning emitted

For more information about this error, try `rustc --explain E0720`.
21 changes: 21 additions & 0 deletions src/test/ui/impl-trait/issue-100075.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
trait Marker {}
impl<T> Marker for T {}

fn maybe<T>(
_t: T,
) -> Option<
//removing the line below makes it compile
&'static T,
> {
None
}

fn _g<T>(t: &'static T) -> &'static impl Marker {
//~^ ERROR cannot resolve opaque type
if let Some(t) = maybe(t) {
return _g(t);
}
todo!()
}

fn main() {}
12 changes: 12 additions & 0 deletions src/test/ui/impl-trait/issue-100075.stderr
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
error[E0720]: cannot resolve opaque type
--> $DIR/issue-100075.rs:13:37
|
LL | fn _g<T>(t: &'static T) -> &'static impl Marker {
| ^^^^^^^^^^^ recursive opaque type
...
LL | return _g(t);
| ----- returning here with type `&impl Marker`

error: aborting due to previous error

For more information about this error, try `rustc --explain E0720`.