Expected associated type, found struct `std::string::String`

I'm getting a big error message that I don't understand. The interesting lines are 15 & 16 in the link: there is a "mismatch" between an associated type and String, but the associated type in the message resolves to String, so it should compile. Is this a known bug? (Unfortunately I don't know how to minimize the code, so I'm hoping that the error message would be enough for someone to know what's going on...)

Are you sure it is a String in this case?

Yes, I'm pretty sure. Even if it weren't, the error message should tell me what it is... It looks like the compiler treats the type as generic even though all the type parameters are specified, so it's a concrete type.

When rustc decides to create super-long error messages, they’re always terrible. I got it a bit more readable by rustfmting the respective types:

error[E0271]: type mismatch resolving `for<'a> T1 == T2`
    --> src/assembler/semantics/directive.rs:569:9
     |
569  |         collect_semantic_actions(|actions| {
     |         ^^^^^^^^^^^^^^^^^^^^^^^^ expected associated type, found struct `std::string::String`
     | 
    ::: src/assembler/semantics/mod.rs:1424:19
     |
1424 |     pub(super) fn collect_semantic_actions<F, S>(f: F) -> Vec<Event<S>>
     |                   ------------------------ required by a bound in this
1425 |     where
1426 |         F: for<'a> FnOnce(TestTokenStreamSemantics<'a, S>) -> TestTokenStreamSemantics<'a, S>,
     |                                                               ------------------------------- required by this bound in `assembler::semantics::tests::collect_semantic_actions`
     |
     = note: expected struct `T3`
                found struct `T4`
     = help: consider constraining the associated type `T5` to `std::string::String` or calling a method that returns `T5`
     = note: for more information, visit https://doc.rust-lang.org/book/ch19-03-advanced-traits.html

with

type T1 = <[closure@src/assembler/semantics/directive.rs:569:34: 583:10 label:_, directive:_, f:_] as std::ops::FnOnce<(
    assembler::semantics::Semantics<
        'a,
        assembler::session::CompositeSession<
            codebase::FileCodebase<'a, (dyn codebase::FileSystem + 'a)>,
            span::fake::FakeSpanSystem<codebase::BufId, ()>,
            assembler::session::MockInterner,
            std::vec::Vec<
                std::rc::Rc<assembler::session::macros::MacroDef<(), std::string::String>>,
            >,
            assembler::session::resolve::BiLevelNameTable<
                assembler::session::macros::MacroId,
                object::Symbol<object::BuiltinDefId, object::UserDefId>,
                std::string::String,
            >,
            assembler::session::builder::ObjectBuilder<()>,
            diagnostics::IgnoreDiagnostics,
            std::vec::Vec<
                assembler::session::Event<
                    object::Symbol<object::BuiltinDefId, object::UserDefId>,
                    assembler::session::macros::MacroId,
                    std::string::String,
                    (),
                    (),
                >,
            >,
        >,
        assembler::semantics::TokenStreamState<
            <assembler::session::CompositeSession<
                codebase::FileCodebase<'a, (dyn codebase::FileSystem + 'a)>,
                span::fake::FakeSpanSystem<codebase::BufId, ()>,
                assembler::session::MockInterner,
                std::vec::Vec<
                    std::rc::Rc<assembler::session::macros::MacroDef<(), std::string::String>>,
                >,
                assembler::session::resolve::BiLevelNameTable<
                    assembler::session::macros::MacroId,
                    object::Symbol<object::BuiltinDefId, object::UserDefId>,
                    std::string::String,
                >,
                assembler::session::builder::ObjectBuilder<()>,
                diagnostics::IgnoreDiagnostics,
                std::vec::Vec<
                    assembler::session::Event<
                        object::Symbol<object::BuiltinDefId, object::UserDefId>,
                        assembler::session::macros::MacroId,
                        std::string::String,
                        (),
                        (),
                    >,
                >,
            > as assembler::session::StringSource>::StringRef,
            <assembler::session::CompositeSession<
                codebase::FileCodebase<'a, (dyn codebase::FileSystem + 'a)>,
                span::fake::FakeSpanSystem<codebase::BufId, ()>,
                assembler::session::MockInterner,
                std::vec::Vec<
                    std::rc::Rc<assembler::session::macros::MacroDef<(), std::string::String>>,
                >,
                assembler::session::resolve::BiLevelNameTable<
                    assembler::session::macros::MacroId,
                    object::Symbol<object::BuiltinDefId, object::UserDefId>,
                    std::string::String,
                >,
                assembler::session::builder::ObjectBuilder<()>,
                diagnostics::IgnoreDiagnostics,
                std::vec::Vec<
                    assembler::session::Event<
                        object::Symbol<object::BuiltinDefId, object::UserDefId>,
                        assembler::session::macros::MacroId,
                        std::string::String,
                        (),
                        (),
                    >,
                >,
            > as span::SpanSource>::Span,
        >,
    >,
)>>::Output;

type T2 = assembler::semantics::Semantics<
    'a,
    assembler::session::CompositeSession<
        codebase::FileCodebase<'a, (dyn codebase::FileSystem + 'a)>,
        span::fake::FakeSpanSystem<codebase::BufId, ()>,
        assembler::session::MockInterner,
        std::vec::Vec<std::rc::Rc<assembler::session::macros::MacroDef<(), std::string::String>>>,
        assembler::session::resolve::BiLevelNameTable<
            assembler::session::macros::MacroId,
            object::Symbol<object::BuiltinDefId, object::UserDefId>,
            std::string::String,
        >,
        assembler::session::builder::ObjectBuilder<()>,
        diagnostics::IgnoreDiagnostics,
        std::vec::Vec<
            assembler::session::Event<
                object::Symbol<object::BuiltinDefId, object::UserDefId>,
                assembler::session::macros::MacroId,
                std::string::String,
                (),
                (),
            >,
        >,
    >,
    assembler::semantics::TokenStreamState<
        <assembler::session::CompositeSession<
            codebase::FileCodebase<'a, (dyn codebase::FileSystem + 'a)>,
            span::fake::FakeSpanSystem<codebase::BufId, ()>,
            assembler::session::MockInterner,
            std::vec::Vec<
                std::rc::Rc<assembler::session::macros::MacroDef<(), std::string::String>>,
            >,
            assembler::session::resolve::BiLevelNameTable<
                assembler::session::macros::MacroId,
                object::Symbol<object::BuiltinDefId, object::UserDefId>,
                std::string::String,
            >,
            assembler::session::builder::ObjectBuilder<()>,
            diagnostics::IgnoreDiagnostics,
            std::vec::Vec<
                assembler::session::Event<
                    object::Symbol<object::BuiltinDefId, object::UserDefId>,
                    assembler::session::macros::MacroId,
                    std::string::String,
                    (),
                    (),
                >,
            >,
        > as assembler::session::StringSource>::StringRef,
        <assembler::session::CompositeSession<
            codebase::FileCodebase<'a, (dyn codebase::FileSystem + 'a)>,
            span::fake::FakeSpanSystem<codebase::BufId, ()>,
            assembler::session::MockInterner,
            std::vec::Vec<
                std::rc::Rc<assembler::session::macros::MacroDef<(), std::string::String>>,
            >,
            assembler::session::resolve::BiLevelNameTable<
                assembler::session::macros::MacroId,
                object::Symbol<object::BuiltinDefId, object::UserDefId>,
                std::string::String,
            >,
            assembler::session::builder::ObjectBuilder<()>,
            diagnostics::IgnoreDiagnostics,
            std::vec::Vec<
                assembler::session::Event<
                    object::Symbol<object::BuiltinDefId, object::UserDefId>,
                    assembler::session::macros::MacroId,
                    std::string::String,
                    (),
                    (),
                >,
            >,
        > as span::SpanSource>::Span,
    >,
>;

type T3 = assembler::semantics::Semantics<
    '_,
    _,
    assembler::semantics::TokenStreamState<
        <assembler::session::CompositeSession<
            codebase::FileCodebase<'_, dyn codebase::FileSystem>,
            span::fake::FakeSpanSystem<codebase::BufId, ()>,
            assembler::session::MockInterner,
            std::vec::Vec<
                std::rc::Rc<assembler::session::macros::MacroDef<(), std::string::String>>,
            >,
            assembler::session::resolve::BiLevelNameTable<
                assembler::session::macros::MacroId,
                object::Symbol<object::BuiltinDefId, object::UserDefId>,
                std::string::String,
            >,
            assembler::session::builder::ObjectBuilder<()>,
            diagnostics::IgnoreDiagnostics,
            std::vec::Vec<
                assembler::session::Event<
                    object::Symbol<object::BuiltinDefId, object::UserDefId>,
                    assembler::session::macros::MacroId,
                    std::string::String,
                    (),
                    (),
                >,
            >,
        > as assembler::session::StringSource>::StringRef,
        <assembler::session::CompositeSession<
            codebase::FileCodebase<'_, dyn codebase::FileSystem>,
            span::fake::FakeSpanSystem<codebase::BufId, ()>,
            assembler::session::MockInterner,
            std::vec::Vec<
                std::rc::Rc<assembler::session::macros::MacroDef<(), std::string::String>>,
            >,
            assembler::session::resolve::BiLevelNameTable<
                assembler::session::macros::MacroId,
                object::Symbol<object::BuiltinDefId, object::UserDefId>,
                std::string::String,
            >,
            assembler::session::builder::ObjectBuilder<()>,
            diagnostics::IgnoreDiagnostics,
            std::vec::Vec<
                assembler::session::Event<
                    object::Symbol<object::BuiltinDefId, object::UserDefId>,
                    assembler::session::macros::MacroId,
                    std::string::String,
                    (),
                    (),
                >,
            >,
        > as span::SpanSource>::Span,
    >,
>;

type T4 = assembler::semantics::Semantics<
    '_,
    _,
    assembler::semantics::TokenStreamState<std::string::String, ()>,
>;

type T5 = <assembler::session::CompositeSession<
    codebase::FileCodebase<'_, dyn codebase::FileSystem>,
    span::fake::FakeSpanSystem<codebase::BufId, ()>,
    assembler::session::MockInterner,
    std::vec::Vec<std::rc::Rc<assembler::session::macros::MacroDef<(), std::string::String>>>,
    assembler::session::resolve::BiLevelNameTable<
        assembler::session::macros::MacroId,
        object::Symbol<object::BuiltinDefId, object::UserDefId>,
        std::string::String,
    >,
    assembler::session::builder::ObjectBuilder<()>,
    diagnostics::IgnoreDiagnostics,
    std::vec::Vec<
        assembler::session::Event<
            object::Symbol<object::BuiltinDefId, object::UserDefId>,
            assembler::session::macros::MacroId,
            std::string::String,
            (),
            (),
        >,
    >,
> as assembler::session::StringSource>::StringRef;

Which boils down to, according to the compiler, this type (T5 from above):

<CompositeSession<
    FileCodebase<'_, dyn FileSystem>,
    FakeSpanSystem<BufId, ()>,
    MockInterner,
    Vec<Rc<MacroDef<(), String>>>,
    BiLevelNameTable<MacroId, Symbol<BuiltinDefId, UserDefId>, String>,
    ObjectBuilder<()>,
    IgnoreDiagnostics,
    Vec<Event<Symbol<BuiltinDefId, UserDefId>, MacroId, String, (), ()>>,
> as StringSource>::StringRef;

not being the same as String.


This is the moment where I’d need to see the impl StringSource for CompositeSession<...> code (in particular the type StringRef = ... line of it) to check to what this reduces.

2 Likes

There are a few issues about rustc occasionally failing to unify types: #70030, #72582. This URLO thread might be another example.