Change:
EDIT: To anyone coming to this from the This Week in Rust CFP: This is currently an unsolved issue, so the first step to tackling this is to figure out where the bug is! That alone would be a huge help. If you want to implement a fix, that'd be great too :) The following program should compile on stable, but doesn't: It with the following error: Note that if we amend as either of the following, (credit to for figuring this out):
Okay, so I came here from the TWIR CFP post, and I thought I would take a stab at this. This is the first time I have ever dug deeply into the internals of rustc itself, so take everything I'm about to say with a grain of salt. I don't have a real understanding of most of the rustc internals yet, so I approached this bug purely experimentally. It may be that what I'm saying is very obvious to somebody who already understands how typechecking and trait resolution work, so I apologize if I'm wasting everyone's time. So I started by playing with the failing example, and there are lots of ways here to get some obviously wrong output from rustc: So I started by looking into why in the world the compiler would output when checking the associated constant when it's obviously in the where clause for the trait impl. After a lot of logging and staring at the code in , I figured out where the trait resolver is supposed to get this information: each obligation's field. I found that this during trait resolution for was empty! so clearly it made sense that the compiler couldn't find an implementation of Foo for F. From there, I figured out that this instance ultimately comes from where it is purposefully constructed as empty. Quickly checking the history of I saw that the original implementation of associated constants did not use an empty , and I'm not sure why an empty is constructed now (though I'm not really sure of anything, I barely understand what's going on here). After some experimentation, I was able to make all of the examples here compile by changing: to to put the where clause for in scope. However, this causes two tests to fail: and . Through experimentation I'm able to fix by limiting where the non-empty instance is passed to only and passing in an empty in other places, but I'm unable to fix without again causing this bug. So I don't think I'm actually fixing the bug here, because I don't understand things well enough yet to know what the right thing to do is, and there's a huge chance I have a lot of this wrong. I'm including all of this information simply in case it helps somebody more knowledgable actually fix it. I hope this is helpful, if it's not helpful then feel free to ignore.
I'm no expert either, but just from the test failures it seems that fix is actually correct. Test failures after applying the fix: has an expected failure, but checked for specific error message, that this issue is about. After the fix the code is still (correctly) rejected, but the error message is more specific to the issue in the code. In the compiler now accepts code that was rejected before. This is no longer an error: The appears similar to the one on this issue: while pointing right at a place in the code that says otherwise. Since impls can use more generic lifetimes (as was ), it would make sense if this code was allowed as well.
Oh, I should have paid more attention to what the tests actually did, thank you for looking at that!
Wow, fantastic work ! I'm not familiar enough with rustc to be able to say anything more than has, but I guess just throw up a PR and we'll see what the reviewers say!
I saw your PR got merged; thanks again for your work digging into this and for the fix!
No problem, glad to help It was more straightforward than I thought it was going to be.

Discussion:
debug!("compare_const_impl(impl_trait_ref={:?})", impl_trait_ref); tcx.infer_ctxt().enter(|infcx| { <del> let param_env = ty::ParamEnv::empty(); </del> <ins> let param_env = tcx.param_env(impl_c.def_id); </ins> let inh = Inherited::new(infcx, impl_c.def_id); let infcx = &inh.infcx;

impl<T: Foo> Bar for T { const FROM: &'static str = "foo"; <del> //~^ ERROR the trait bound `T: Foo` is not satisfied [E0277] </del> <ins> //~^ ERROR implemented const `FROM` has an incompatible type for trait [E0326] </ins> } fn main() {}

<del> error[E0277]: the trait bound `T: Foo` is not satisfied --> $DIR/associated-const-generic-obligations.rs:14:5 </del> <ins> error[E0326]: implemented const `FROM` has an incompatible type for trait --> $DIR/associated-const-generic-obligations.rs:14:17 </ins> | <ins> LL |     const FROM: Self::Out; |                 --------- type in trait ... </ins> LL |     const FROM: &'static str = "foo"; <del> |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `Foo` is not implemented for `T` </del> <ins> |                 ^^^^^^^^^^^^ expected associated type, found reference </ins> | <del> = help: consider adding a `where T: Foo` bound </del> <ins> = note: expected type `<T as Foo>::Out` found type `&'static str` </ins> error: aborting due to previous error <del> For more information about this error, try `rustc --explain E0277`. </del> <ins> For more information about this error, try `rustc --explain E0326`. </ins>

<ins> // compile-pass trait ConstDefault { const DEFAULT: Self; } trait Foo: Sized {} trait FooExt: Foo { type T: ConstDefault; } trait Bar<F: FooExt> { const T: F::T; } impl<F: FooExt> Bar<F> for () { const T: F::T = <F::T as ConstDefault>::DEFAULT; } fn main() {} </ins>

const AC: Option<&'b str>; } <del> struct OKStruct { } </del> <ins> struct OKStruct1 { } </ins> <del> impl<'a: 'b, 'b> Anything<'a, 'b> for OKStruct { </del> <ins> impl<'a: 'b, 'b> Anything<'a, 'b> for OKStruct1 { </ins> const AC: Option<&'b str> = None; } <del> struct FailStruct1 { } </del> <ins> struct FailStruct { } </ins> <del> impl<'a: 'b, 'b, 'c> Anything<'a, 'b> for FailStruct1 { </del> <ins> impl<'a: 'b, 'b, 'c> Anything<'a, 'b> for FailStruct { </ins> const AC: Option<&'c str> = None; //~^ ERROR: mismatched types } <del> struct FailStruct2 { } </del> <ins> struct OKStruct2 { } </ins> <del> impl<'a: 'b, 'b> Anything<'a, 'b> for FailStruct2 { </del> <ins> impl<'a: 'b, 'b> Anything<'a, 'b> for OKStruct2 { </ins> const AC: Option<&'a str> = None; <del> //~^ ERROR: mismatched types </del> } fn main() {}

note: the lifetime 'c as defined on the impl at 20:18... --> $DIR/trait-associated-constant.rs:20:18 | <del> LL | impl<'a: 'b, 'b, 'c> Anything<'a, 'b> for FailStruct1 { </del> <ins> LL | impl<'a: 'b, 'b, 'c> Anything<'a, 'b> for FailStruct { </ins> |                  ^^ note: ...does not necessarily outlive the lifetime 'b as defined on the impl at 20:14 --> $DIR/trait-associated-constant.rs:20:14 | <del> LL | impl<'a: 'b, 'b, 'c> Anything<'a, 'b> for FailStruct1 { </del> <ins> LL | impl<'a: 'b, 'b, 'c> Anything<'a, 'b> for FailStruct { </ins> |              ^^ <del> error[E0308]: mismatched types --> $DIR/trait-associated-constant.rs:28:5 | LL |     const AC: Option<&'a str> = None; |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ lifetime mismatch | = note: expected type `std::option::Option<&'b str>` found type `std::option::Option<&'a str>` note: the lifetime 'a as defined on the impl at 27:6... --> $DIR/trait-associated-constant.rs:27:6 | LL | impl<'a: 'b, 'b> Anything<'a, 'b> for FailStruct2 { |      ^^ note: ...does not necessarily outlive the lifetime 'b as defined on the impl at 27:14 --> $DIR/trait-associated-constant.rs:27:14 | LL | impl<'a: 'b, 'b> Anything<'a, 'b> for FailStruct2 { |              ^^ error: aborting due to 2 previous errors </del> <ins> error: aborting due to previous error </ins> For more information about this error, try `rustc --explain E0308`.