-
Notifications
You must be signed in to change notification settings - Fork 13k
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
ICE with impl Fn alias. #65918
Comments
That code is a mess! After an hour of digging through the code and removing half of it - the code that triggers the error is: I try to produce a MCVE out of it currently |
@hellow554 Yes, the code is in a very work-in-progress state, so there are a lot of places which should be refactored or even removed, sorry for that. The line that I mentioned in my original post calls the function that you have pointed to. The function alone compiles well to WASM. It does not compile when used as follow: https://github.com/luna/basegl/blob/9fac17b2ae69b5a63b6555529e431db1a740f11a/lib/core/src/lib.rs#L126 |
Seems to be related to #![feature(type_alias_impl_trait)]
mod attribute {
use std::convert::TryFrom;
pub struct Attribute<T, OnSet, OnResize> {
_m: std::marker::PhantomData<(T, OnSet, OnResize)>,
}
pub enum AnyAttribute<OnSet, OnResize> {
Varianti32(Attribute<i32, OnSet, OnResize>),
}
impl<'t, T, S> TryFrom<&'t AnyAttribute<T, S>> for &'t Attribute<i32, T, S> {
type Error = ();
fn try_from(_: &'t AnyAttribute<T, S>) -> Result<&'t Attribute<i32, T, S>, Self::Error> {
unimplemented!()
}
}
pub trait IsAttribute<OnSet, OnResize> {
fn add_element(&mut self);
fn len(&self) -> usize;
}
}
mod scope {
use std::convert::{TryFrom, TryInto};
use std::marker::PhantomData;
use std::ops::Index;
use crate::attribute as attr;
pub struct TypedIndex<T> {
pub ix: usize,
phantom: PhantomData<T>,
}
impl<T> TypedIndex<T> {
pub fn new() -> Self {
unimplemented!()
}
}
pub struct Scope<OnDirty> {
pub attributes: Vec<AnyAttribute<OnDirty>>,
}
pub type Attribute<T, OnDirty> = attr::Attribute<
T,
DummyT<OnDirty>,
DummyT<OnDirty>,
>;
pub type AnyAttribute<OnDirty> = attr::AnyAttribute<
DummyT<OnDirty>,
DummyT<OnDirty>,
>;
pub type DummyT<T> = impl Fn();
pub fn _dummy<T>() -> DummyT<T> { move || {} }
impl<OnDirty> Scope<OnDirty> {
pub fn ne() -> Self {
unimplemented!()
}
}
impl<T, OnDirty> Index<TypedIndex<T>> for Scope<OnDirty>
where
for<'t> &'t T: TryFrom<&'t AnyAttribute<OnDirty>>,
{
type Output = T;
fn index(&self, t: TypedIndex<T>) -> &Self::Output {
self.attributes.index(t.ix).try_into().ok().unwrap()
}
}
}
pub type Closure_workspace_on_change_handler = impl Fn() + Clone;
pub fn workspace_on_change_handler() -> Closure_workspace_on_change_handler {
move || {}
}
pub type Attribute<T> = scope::Attribute<T, Closure_workspace_on_change_handler>;
pub type AttributeScope = scope::Scope<Closure_workspace_on_change_handler>;
pub fn start() {
let pos_id = scope::TypedIndex::new();
let pt_scope = AttributeScope::ne();
let _pos: &Attribute<i32> = &pt_scope[pos_id];
} I may give it a shot later, but now I'm gonna head home :) |
@hellow554 that is amazing! I've created yet shorter version (still, there may be things to simplify here): #![feature(type_alias_impl_trait)]
use std::convert::{TryFrom, TryInto};
use std::marker::PhantomData;
use std::ops::Index;
pub struct TypedIndex<T> {
pub ix: usize,
phantom: PhantomData<T>,
}
impl<T> TypedIndex<T> {
pub fn new() -> Self {
unimplemented!()
}
}
pub type DummyT<T> = impl Fn();
pub type Dummy = impl Fn();
pub fn _dummy() -> Dummy { move || {} }
pub fn _dummy_t<T>() -> DummyT<T> { move || {} }
pub enum Variants<T> {
V(A1<T>),
}
impl<'t, S> TryFrom<&'t Variants<S>> for &'t A1<S> {
type Error = ();
fn try_from(_: &'t Variants<S>) -> Result<&'t A1<S>, Self::Error> {
unimplemented!()
}
}
pub type Variants2<OnDirty> = Variants<DummyT<OnDirty>>;
pub struct Scope<OnDirty> {
pub attributes: Vec<Variants2<OnDirty>>,
}
impl<OnDirty> Scope<OnDirty> {
pub fn new() -> Self {
unimplemented!()
}
}
impl<T, OnDirty> Index<TypedIndex<T>> for Scope<OnDirty>
where
for<'t> &'t T: TryFrom<&'t Variants2<OnDirty>>,
{
type Output = T;
fn index(&self, t: TypedIndex<T>) -> &Self::Output {
self.attributes.index(t.ix).try_into().ok().unwrap()
}
}
pub struct A1 <T> (std::marker::PhantomData<(T)>);
pub type A2<T> = A1 <DummyT<T>>;
pub type A3 = A2 <Dummy>;
pub type Scope2 = Scope<Dummy>;
pub fn start() {
let pos_id = TypedIndex::new();
let pt_scope = Scope2::new();
let _pos: &A3 = &pt_scope[pos_id];
} |
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
@hellow554 thank you for tracking it down ❤️ |
@wdanilo could you please change the title of this issue to something different, e.g. "ICE with impl Fn alias"? It's not about WASM anymore ;) |
Because a lot has changed, here's a summary: MCVE#![feature(type_alias_impl_trait)]
use std::marker::PhantomData;
/* copied Index and TryFrom for convinience (and simplicity) */
trait MyIndex<T> {
type O;
fn my_index(self) -> Self::O;
}
trait MyFrom<T>: Sized {
type Error;
fn my_from(value: T) -> Result<Self, Self::Error>;
}
/* MCVE starts here */
trait F {}
impl F for () {}
type DummyT<T> = impl F;
fn _dummy_t<T>() -> DummyT<T> {}
struct Phantom1<T>(PhantomData<T>);
struct Phantom2<T>(PhantomData<T>);
struct Scope<T>(Phantom2<DummyT<T>>);
impl<T> Scope<T> {
fn new() -> Self {
unimplemented!()
}
}
impl<T> MyFrom<Phantom2<T>> for Phantom1<T> {
type Error = ();
fn my_from(_: Phantom2<T>) -> Result<Self, Self::Error> {
unimplemented!()
}
}
impl<T: MyFrom<Phantom2<DummyT<U>>>, U> MyIndex<Phantom1<T>> for Scope<U> {
type O = T;
fn my_index(self) -> Self::O {
MyFrom::my_from(self.0).ok().unwrap()
}
}
fn main() {
let _pos: Phantom1<DummyT<()>> = Scope::new().my_index();
} Backtrace
|
Relevant log output:
It looks like I think the solution is to normalize the |
triage: has PR. marking P-high, removing I-nominated. |
When we normalize a type using a ParamEnv with a reveal mode of RevealMode::All, we will normalize opaque types to their underlying types (e.g. `type MyOpaque = impl Foo` -> `StructThatImplsFoo`). However, the ParamEnv may still have predicates referring to the un-normalized opaque type (e.g. `<T as MyTrait<MyOpaque>>`). This can cause trait projection to fail, since a type containing normalized opaque types will not match up with the un-normalized type in the `ParamEnv`. To fix this, we now explicitly normalize all opaque types in caller_bounds of a `ParamEnv` when changing its mode to `RevealMode::All`. This ensures that all predicatse will refer to the underlying types of any opaque types involved, allowing them to be matched up properly during projection. To reflect the fact that normalization is occuring, `ParamEnv::with_reveal_all` is renamed to `ParamEnv::with_reveal_all_normalized` Fixes rust-lang#65918
Normalize all opaque types when converting ParamEnv to Reveal::All When we normalize a type using a ParamEnv with a reveal mode of RevealMode::All, we will normalize opaque types to their underlying types (e.g. `type MyOpaque = impl Foo` -> `StructThatImplsFoo`). However, the ParamEnv may still have predicates referring to the un-normalized opaque type (e.g. `<T as MyTrait<MyOpaque>>`). This can cause trait projection to fail, since a type containing normalized opaque types will not match up with the un-normalized type in the `ParamEnv`. To fix this, we now explicitly normalize all opaque types in caller_bounds of a `ParamEnv` when changing its mode to `RevealMode::All`. This ensures that all predicatse will refer to the underlying types of any opaque types involved, allowing them to be matched up properly during projection. To reflect the fact that normalization is occuring, `ParamEnv::with_reveal_all` is renamed to `ParamEnv::with_reveal_all_normalized` Fixes #65918
…nikomatsakis Normalize all opaque types when converting ParamEnv to Reveal::All When we normalize a type using a ParamEnv with a reveal mode of RevealMode::All, we will normalize opaque types to their underlying types (e.g. `type MyOpaque = impl Foo` -> `StructThatImplsFoo`). However, the ParamEnv may still have predicates referring to the un-normalized opaque type (e.g. `<T as MyTrait<MyOpaque>>`). This can cause trait projection to fail, since a type containing normalized opaque types will not match up with the un-normalized type in the `ParamEnv`. To fix this, we now explicitly normalize all opaque types in caller_bounds of a `ParamEnv` when changing its mode to `RevealMode::All`. This ensures that all predicatse will refer to the underlying types of any opaque types involved, allowing them to be matched up properly during projection. To reflect the fact that normalization is occuring, `ParamEnv::with_reveal_all` is renamed to `ParamEnv::with_reveal_all_normalized` Fixes rust-lang#65918
Hi,
I'm building a project and I'm using the nightly channel. I was testing it with several builds between 2019-09-20 and 2019-10-27, all with the same results – when targetting native, the compilation succeeds, when targetting WASM, we see ICE.
Unfortunately, it was hard for me to minimize the example. Fortunately, the codebase is pretty small. Here is the exact commit: enso-org/ide@9fac17b
After downloading it you can run
cargo build
and it should succeed. But if you run./scripts/build.sh
(which is 1-line wrapper overwasm-pack
), we get:After commenting out this line, everything should compile OK (WASM target should compile as well): https://github.com/luna/basegl/blob/9fac17b2ae69b5a63b6555529e431db1a740f11a/lib/core/src/lib.rs#L126
EDIT
The backtrace from the compiler is not very helpful:
However, there is some additional info:
The text was updated successfully, but these errors were encountered: