Skip to content

global_allocator can not not be defined inside module #44113

Closed

Description

@rkapl

When trying define a global allocator inside a module, you get a weird error message: [E0432]: unresolved import super. The global_allocator is expanded to code containing use super::<varname> but I don't know why rustc fails to resolve that in this case. Happens with both inline and file modules.

Looks like the module that is created by expanding global_allocator thinks its parent is the root crate despite being in the breaks module.

Example:

#![feature(global_allocator, allocator_api)]                                                                                                                                                                       
                                                                                                                                                                                                                   
struct TAlloc;                                                                                                                                                                                                     
                                                                                                                                                                                                                   
unsafe impl<'a> std::heap::Alloc for &'a TAlloc{                                                                                                                                                                   
    unsafe fn alloc(&mut self, _layout: std::heap::Layout) -> std::result::Result<*mut u8, std::heap::AllocErr> {                                                                                                  
        return Err(std::heap::AllocErr::Unsupported{details: "Stub allocator"});                                                                                                                                   
    }                                                                                                                                                                                                              
    unsafe fn dealloc(&mut self, _ptr: *mut u8, _layout: std::heap::Layout) {                                                                                                                                      
    }                                                                                                                                                                                                              
}                                                                                                                                                                                                                  
                                                                                                                                                                                                                   
mod breaks{                                                                                                                                                                                                        
    #[global_allocator]                                                                                                                                                                                            
    static ALLOCATOR: ::TAlloc = ::TAlloc;                                                                                                                                                                         
}                                                                                                                                                                                                                  
                                                                                                                                                                                                                   
pub fn main() {                                                                                                                                                                                                    
}

causes:

error[E0432]: unresolved import `super`
  --> alloc.rs:15:5
   |
15 |     static ALLOCATOR: ::TAlloc = ::TAlloc;
   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ no `ALLOCATOR` in the root

Activity

  1. mattico commented on Sep 27, 2017

    @mattico
    Contributor

    I looked into this a bit, writing some notes here so I don't forget what I found.

    The problem is here:

    let super_path = f.cx.path(f.span, vec![
    Ident::from_str("super"),
    f.global,
    ]);

    The Path for the allocator is hard-coded to be super::<allocator name>. We need to instead get a proper Path for f.global.

    There may be a function hidden in the compiler somewhere that can help get a Path for an Item. If there isn't we could keep a Vec<Mod> as we traverse modules and convert that to a Path if we find an allocator definition.

  2. mattico commented on Sep 27, 2017

    @mattico
    Contributor

    Another option is to generate stub impls of the global alloc functions in the AST but then fill them out later when there's more information available.

  3. whitequark commented on Oct 19, 2017

    @whitequark
    Contributor

    To add to this, this is also broken:

    pub fn main() {
        #[global_allocator]
        static ALLOCATOR: ::TAlloc = ::TAlloc;
    }
  4. mark-i-m commented on Mar 22, 2018

    @mark-i-m
    Contributor
  5. mark-i-m commented on Mar 24, 2018

    @mark-i-m
    Contributor

    Started working on this... It's very WIP at the moment, though. If anyone has feedback, let me know.

  6. added a commit that references this issue on Jun 25, 2018
  7. steveklabnik commented on Apr 3, 2019

    @steveklabnik
    Contributor

    We now have a good error for this:

    error: `global_allocator` cannot be used in submodules
     --> src/main.rs:7:5
      |
    7 |     static MY_HEAP: Heap = Heap::default();
      |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    

    So the real question is, is this something we want to enable in the future? If so, then this shouldn't be closed, and the bug would be tracking that. If we do not, then this should be closed.

  8. mark-i-m commented on Apr 3, 2019

    @mark-i-m
    Contributor

    Personally, i would like for that to be possible. For example, when building an OS, it would be nice to be able to everything in a memory management module. Currently, you have to break that abstraction to put the allocator in thr crate root, which then requires exposing the implementation outside the memory management module.

  9. mark-i-m commented on Apr 3, 2019

    @mark-i-m
    Contributor

    So I realized that I never gave an update here. The current status is as follows:

    About a year ago, I attempted to implement a fix, but we ran into a lot of weird hygiene issues (that even alexcrichton wasn't able to help with). Then, I changed course and implemented the error that Steve posted above. That's about all I know how to do, and that was the end of my endeavors in this space.

    Somebody with expertise in macro/hygiene wizardry and compiler internals is needed to fix the problems we ran into in #49320.

  10. rkapl commented on Apr 3, 2019

    @rkapl
    Author

    For me, the error message is more important than solving the problem perfectly. In my use case, i have just moved the allocator to the root -- but the real problem was finding this solution.

  11. jq-rs commented on Apr 25, 2019

    @jq-rs

    Adding submodule support may be useful when combining several crates with custom global allocator with c libraries. With several crates the ´´´__rg_alloc´´´ symbol is overlapping in the linking phase and linking is failing. Or is there a workaround already for this (besides allowing multidefs)?

  12. mark-i-m commented on Apr 25, 2019

    @mark-i-m
    Contributor

    I think it is intentionally disallowed to have multiple global allocators. After all, they would no longer be global...

  13. jq-rs commented on Apr 25, 2019

    @jq-rs

    In this case they are the same allocator as they are using the same global alloc crate. Still, as they are from different internal crates, they are seen as different allocators during linking. Multidefs is the workaround, but it of course may cause other issues elsewhere. But yes, I agree that maybe submodules is not the way to properly solve this problem.

  14. petrochenkov commented on Jul 16, 2019

    @petrochenkov
    Contributor

    Fixed in #62735.

  15. added 4 commits that reference this issue on Jul 24, 2019
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    A-allocatorsArea: Custom and system allocatorsC-bugCategory: This is a bug.T-libs-api[DEPRECATED; DO NOT USE]

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions