Join GitHub today
GitHub is home to over 31 million developers working together to host and review code, manage projects, and build software together.
Sign upICE: librustc/traits/codegen/mod.rs:68: Encountered error `OutputTypeParameterMismatch` #53420
Comments
This comment has been minimized.
This comment has been minimized.
trait Lt<'a> {
type T;
}
impl<'a> Lt<'a> for () {
type T = ();
}
fn main() {
let _:fn(<() as Lt<'_>>::T) = |()| {};
} |
This comment has been minimized.
This comment has been minimized.
|
The error message actually tells us the reason:
So the unification between Interestingly, the following works: fn main() {
let _: fn(_) = |_:<Id<()> as Lt<'_>>::T| {};
}but creates another ICE when try to call the function: trait Lt<'a> {
type T;
}
struct Id<T>(T);
impl<'a,T> Lt<'a> for Id<T> {
type T = T;
}
fn main() {
let f: fn(_) = |_:<Id<()> as Lt<'_>>::T| {};
f(())
}where the error message again contains:
So, my guess is that somehow this unification passed. However, some work was missing to actually substitute it before generating MIR, and the MIR checker then fails because it didn't follow the same logic to justify the unification. |
This comment has been minimized.
This comment has been minimized.
|
The following is working, but the MIR shows a potential reason that seems causes the issue. trait Lt<'a> {
type T;
}
struct Id<T>(T);
impl<'a,T> Lt<'a> for Id<T> {
type T = T;
}
fn main() {
let _v: <Id<()> as Lt<'_>>::T = ();
let _f: fn(_) = |_:<Id<()> as Lt<'_>>::T| {};
//ICE: broken MIR in DefId
//_f(_v)
}In generated MIR, it contains the following:
I think this should be subsituted and change to
Interestingly, the variable
Further investigate shows that if we remove the lifetime the problem is resolved. So it seems that the erasure of lifetime wasn't done properly and left behind things that can be substituted? Issues maybe releated: |
earthengine
referenced this issue
Aug 17, 2018
Merged
Fix ICE when rustdoc encounters certain usages of HRTBs #52990
This comment has been minimized.
This comment has been minimized.
|
Manually desugaring //Working
let _:&FnOnce<(<() as Lt<'_>>::T,),Output=()> = &|_|{};
//Not working
let _:&FnOnce(<() as Lt<'_>>::T) = &|_|{};Suggests the problem is in desugaring More example: let f:&FnOnce(_)= &|_:<() as Lt<'_>>::T|{};compiled into MIR (which is WRONG):
let f:&mut FnMut<(<() as Lt<'_>>::T,),Output=()> = &mut |_|{};compiled into MIR (CORRECT)
|
This comment has been minimized.
This comment has been minimized.
|
A more scary ICE: panic with messages that is irrelevant to the code (nightly only with fn main() {
let v:<() as Lt<'_>>::T = ();
let f:&mut FnMut<(_,),Output=()> = &mut |_:<() as Lt<'_>>::T|{};
f(v);
}Error mesage:
I run a local compiler that was compiled from source code, and modifyed the src\librustc_codegen_llvm\back\link.rs file, so function So if I am right, the thread that do MIRI verification was running simultaneously with the LLVM codegen and linker. But MIRI thread issued an error at an unfortunate time point so it crashes the profiler thread. Compare to the HRTB broken MIR issue, I think this is more serious and so I am going to create another issue. |
earthengine
referenced this issue
Aug 17, 2018
Open
ICE: "broken MIR in DefId" when assigning mismatched closure to `FnMut` #53448
alexreg
referenced this issue
Aug 23, 2018
Merged
Move with_globals setup from run_compiler to run #53624
This comment has been minimized.
This comment has been minimized.
|
I need answer of the following question: When should So I suppose the fix would be in the monorphization. After monorphization the substitution should be done but it didn't, which causes problems in codegen. |
This comment has been minimized.
This comment has been minimized.
|
Found the following code in "/src/librustc/traits/select.rs": /// In the case of closure types and fn pointers,
/// we currently treat the input type parameters on the trait as
/// outputs. This means that when we have a match we have only
/// considered the self type, so we have to go back and make sure
/// to relate the argument types too. This is kind of wrong, but
/// since we control the full set of impls, also not that wrong,
/// and it DOES yield better error messages (since we don't report
/// errors as if there is no applicable impl, but rather report
/// errors are about mismatched argument types.
///
/// Here is an example. Imagine we have a closure expression
/// and we desugared it so that the type of the expression is
/// `Closure`, and `Closure` expects an int as argument. Then it
/// is "as if" the compiler generated this impl:
///
/// impl Fn(int) for Closure { ... }
///
/// Now imagine our obligation is `Fn(usize) for Closure`. So far
/// we have matched the self-type `Closure`. At this point we'll
/// compare the `int` to `usize` and generate an error.
///
/// Note that this checking occurs *after* the impl has selected,
/// because these output type parameters should not affect the
/// selection of the impl. Therefore, if there is a mismatch, we
/// report an error to the user.
fn confirm_poly_trait_refs(&mut self,
obligation_cause: ObligationCause<'tcx>,
obligation_param_env: ty::ParamEnv<'tcx>,
obligation_trait_ref: ty::PolyTraitRef<'tcx>,
expected_trait_ref: ty::PolyTraitRef<'tcx>)
-> Result<Vec<PredicateObligation<'tcx>>, SelectionError<'tcx>>
{
let obligation_trait_ref = obligation_trait_ref.clone();
self.infcx
.at(&obligation_cause, obligation_param_env)
.sup(obligation_trait_ref, expected_trait_ref)
.map(|InferOk { obligations, .. }| obligations)
.map_err(|e| OutputTypeParameterMismatch(expected_trait_ref, obligation_trait_ref, e))
}seems like the following assumsion
didn't hold in this case so the error is reported. So the conclusion: in "/src/librustc/traits/select.rs", pub fn select(...
let candidate = match self.candidate_from_obligation(&stack) {...
...
match self.confirm_candidate(obligation, candidate) {...
...
}the call One obvious solution is to ensure we substitute associate types after |
This comment has been minimized.
This comment has been minimized.
|
Or, is the following (/src/librustc/traits/select.rs) fn confirm_fn_pointer_candidate(&mut self, obligation: &TraitObligation<'tcx>)
-> Result<VtableFnPointerData<'tcx, PredicateObligation<'tcx>>, SelectionError<'tcx>>
{
debug!("confirm_fn_pointer_candidate({:?})",
obligation);
// ok to skip binder; it is reintroduced below
let self_ty = self.infcx.shallow_resolve(*obligation.self_ty().skip_binder());
let sig = self_ty.fn_sig(self.tcx());
let trait_ref =
self.tcx().closure_trait_ref_and_return_type(obligation.predicate.def_id(),
self_ty,
sig,
util::TupleArgumentsFlag::Yes)
.map_bound(|(trait_ref, _)| trait_ref);
let Normalized { value: trait_ref, obligations } =
project::normalize_with_depth(self,
obligation.param_env,
obligation.cause.clone(),
obligation.recursion_depth + 1,
&trait_ref);
self.confirm_poly_trait_refs(obligation.cause.clone(),
obligation.param_env,
obligation.predicate.to_poly_trait_ref(),
trait_ref)?;
Ok(VtableFnPointerData { fn_ty: self_ty, nested: obligations })
}correct? I mean the following assumsion:
given the fact that we have trouble to unify |
This comment has been minimized.
This comment has been minimized.
|
I see you have been working on #18993 (HRTB). This issue seems to be in the concept "late bound regions" you introduced: Can you please look into this and tell me when it is supposed to be bound? (I can see the difficulty here: there is a lifetime but was never specified and no clue was given to infer it, making it hard to assume anything on it) |
This comment has been minimized.
This comment has been minimized.
|
A slightly adjusted from the minimal reproducable trait Lt<'a> {
type T;
}
impl<'a> Lt<'a> for () {
type T = ();
}
fn main() {
let _:fn(()) = |_:<() as Lt<'_>>::T| {};
}gives a normal, but still confusing error message:
This is consistent in both stable and nightly(2015 or 2018). trait Lt<'a> {
type T;
}
impl<'a> Lt<'a> for () {
type T = ();
}
fn test<'a>() {
let _:fn(<() as Lt<'a>>::T) = |()| {};
}
fn main() {
test();
}is working, but will trigger this ICE if remove the |
earthengine
referenced this issue
Sep 11, 2018
Closed
Lifetime inference failed on HRTB input #54124
memoryruins
added
the
I-ICE
label
Sep 11, 2018
earthengine
referenced this issue
Sep 13, 2018
Open
ATC-like for<'a> Fn(<X as Trait<'a>>::Type) does not consistently normalize (and can ICE). #52812
pnkfelix
added
the
T-compiler
label
Sep 18, 2018
This comment has been minimized.
This comment has been minimized.
|
assigning self for preliminary investigation |
pnkfelix
self-assigned this
Oct 4, 2018
pnkfelix
added
the
P-high
label
Oct 4, 2018
This comment has been minimized.
This comment has been minimized.
|
Since this is an ICE and is not using any unstable features (and in fact, reproduces on the stable channel), I have tagged it as P-high for now. That means we'll be visiting it regularly during the weekly compiler team meeting. |
This comment has been minimized.
This comment has been minimized.
|
Also: Thank you @earthengine for your patience as well as your copious notes from your own investigations. My current hypothesis is that normalization is supposed to be doing the substitution mapping |
pnkfelix
added
A-typesystem
A-associated-items
labels
Oct 4, 2018
This comment has been minimized.
This comment has been minimized.
|
Discussed at T-compiler meeting. Seems to be duplicate of issue #29997. Closing as duplicate. |
earthengine commentedAug 16, 2018
I was attempt to apply the trick of this blog post to improve my named closures crate. But I run into this ICE, which is unfortunately in stable.
https://play.rust-lang.org/?gist=22299e701c9bdb472a5fc8fe303b7fa1&version=stable&mode=debug&edition=2015
This is freshly occur so I didn't simplify the code.