Skip to content
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

const_generics: link fails with undefined reference, hidden symbol isn't defined #83972

Closed
Dirbaio opened this issue Apr 7, 2021 · 7 comments · Fixed by #100315
Closed

const_generics: link fails with undefined reference, hidden symbol isn't defined #83972

Dirbaio opened this issue Apr 7, 2021 · 7 comments · Fixed by #100315
Labels
A-const-generics Area: const generics (parameters and arguments) A-linkage Area: linking into static, shared libraries and binaries C-bug Category: This is a bug. F-generic_const_exprs `#![feature(generic_const_exprs)]` T-compiler Relevant to the compiler team, which will review and decide on the PR/issue.

Comments

@Dirbaio
Copy link
Contributor

Dirbaio commented Apr 7, 2021

This code (playground)

#![feature(const_generics)]

pub trait Foo {
    fn foo(&self);
}

pub struct FooImpl<const N: usize>;
impl<const N: usize> Foo for FooImpl<N> {
    fn foo(&self) {}
}

pub trait Bar: 'static {
    type Foo: Foo;
    fn get() -> &'static Self::Foo;
}

struct BarImpl;
impl Bar for BarImpl {
    type Foo = FooImpl<{ 4 }>;
    fn get() -> &'static Self::Foo {
        &FooImpl
    }
}

pub fn boom<B: Bar>() {
    B::get().foo();
}

fn main() {
    boom::<BarImpl>();
}

fails to link with


error: linking with `cc` failed: exit status: 1
  |
  = note: "cc" "-m64" "-Wl,--eh-frame-hdr" "-Wl,-znoexecstack" "-Wl,--as-needed" "-L" "/playground/.rustup/toolchains/nightly-x86_*snip*own-linux-gnu/lib/libcompiler_builtins-8b33f9cbbc9652fe.rlib" "-Wl,-Bdynamic" "-lgcc_s" "-lutil" "-lrt" "-lpthread" "-lm" "-ldl" "-lc"
  = note: /usr/bin/ld: /playground/target/debug/deps/playground-dea6a74639071602.playground.27snrtcg-cgu.0.rcgu.o: in function `playground::boom':
          /playground/src/main.rs:26: undefined reference to `<playground::FooImpl<_> as playground::Foo>::foo'
          /usr/bin/ld: /playground/target/debug/deps/playground-dea6a74639071602: hidden symbol `_ZN64_$LT$playground..FooImpl$LT$_$GT$$u20$as$u20$playground..Foo$GT$3foo17hc9e5ef50b3fc24d9E' isn't defined
          /usr/bin/ld: final link failed: bad value
          collect2: error: ld returned 1 exit status

rustc --version --verbose:

rustc 1.53.0-nightly (c051c5ddd 2021-04-06)
binary: rustc
commit-hash: c051c5ddda79f45fad196ca3a4690251e377d043
commit-date: 2021-04-06
host: x86_64-unknown-linux-gnu
release: 1.53.0-nightly
LLVM version: 12.0.0
@Dirbaio Dirbaio added the C-bug Category: This is a bug. label Apr 7, 2021
@Dirbaio
Copy link
Contributor Author

Dirbaio commented Apr 7, 2021

Builds correctly with rustc 1.53.0-nightly (5e65467ef 2021-03-26)
Fails with rustc 1.53.0-nightly (9b0edb7fd 2021-03-27)

@jonas-schievink jonas-schievink added A-const-generics Area: const generics (parameters and arguments) A-linkage Area: linking into static, shared libraries and binaries T-compiler Relevant to the compiler team, which will review and decide on the PR/issue. labels Apr 7, 2021
@eggyal
Copy link
Contributor

eggyal commented Apr 7, 2021

Fails with rustc 1.53.0-nightly (9b0edb7fd 2021-03-27)

@Dirbaio 9b0edb7fd appears to be nightly-2021-03-28, which I agree is the first regression.

searched nightlies: from nightly-2021-03-26 to nightly-2021-04-07
regressed nightly: nightly-2021-03-28
searched commits: from 5e65467 to 9b0edb7
regressed commit: 9b0edb7

bisected with cargo-bisect-rustc v0.6.0

Host triple: x86_64-unknown-linux-gnu
Reproduce with:

cargo bisect-rustc --start 2021-03-26 

@Dirbaio
Copy link
Contributor Author

Dirbaio commented Apr 7, 2021

The code I originally found this in does require #![feature(const_generics)] and #![feature(const_evaluatable_checked)], but while minimizing it I arrived to this.

The error also disappears when removing the braces in { 4 }

@tmiasko
Copy link
Contributor

tmiasko commented Apr 7, 2021

const_generics feature enables lazy normalization. It seems that in one place a symbol name is constructed using an unevaluated const, while the other uses the evaluated one. This crates a mismatch in legacy symbol mangling scheme. The issue also disappears in -Zsymbol-mangling-version=v0 which evaluates the const during mangling.

$ rustc -Zprint-mono-items=lazy -Zverbose ...
MONO_ITEM fn <FooImpl<Const(Unevaluated(Unevaluated { def: WithOptConstParam { did: DefId(0:18 ~ a[317d]::{impl#1}::Foo::{constant#0}), const_param_did: Some(DefId(0:7 ~ a[317d]::FooImpl::N)) }, substs: [], promoted: None }): usize)> as Foo>::foo @@ a.7rcbfp3g-cgu.0[Internal]
input to MirNeighborCollector::monomorphize    for<'r> fn(&'r <B as Bar>::Foo) {<<B as Bar>::Foo as Foo>::foo}
after subst_mir_and_normalize_erasing_regions  for<'r> fn(&'r FooImpl<{ 4 }>) {<FooImpl<{ 4 }> as Foo>::foo}
after an exra normalize_erasing_regions (*)    for<'r> fn(&'r FooImpl<4_usize>) {<FooImpl<4_usize> as Foo>::foo}

Verbose:

input to MirNeighborCollector::monomorphize    for<'r> fn(&ReLateBound(DebruijnIndex(0), BoundRegion { var: 0, kind: BrNamed('r) }) <B as Bar>::Foo) {<<B as Bar>::Foo as Foo>::foo}
after subst_mir_and_normalize_erasing_regions  for<'r> fn(&ReLateBound(DebruijnIndex(0), BoundRegion { var: 0, kind: BrNamed('r) }) FooImpl<Const(Unevaluated(Unevaluated { def: WithOptConstParam { did: DefId(0:18 ~ a[317d]::{impl#1}::Foo::{constant#0}), const_param_did: Some(DefId(0:7 ~ a[317d]::FooImpl::N)) }, substs: [], promoted: None }): usize)>) {<FooImpl<Const(Unevaluated(Unevaluated { def: WithOptConstParam { did: DefId(0:18 ~ a[317d]::{impl#1}::Foo::{constant#0}), const_param_did: Some(DefId(0:7 ~ a[317d]::FooImpl::N)) }, substs: [], promoted: None }): usize)> as Foo>::foo}
after an extra normalize_erasing_regions (*)   for<'r> fn(&ReLateBound(DebruijnIndex(0), BoundRegion { var: 0, kind: BrNamed('r) }) FooImpl<Const(Value(Scalar(0x0000000000000004)): usize)>) {<FooImpl<Const(Value(Scalar(0x0000000000000004)): usize)> as Foo>::foo}

@agausmann
Copy link
Contributor

I'm seeing a similar error: #97186, with a very similar example!

It seems that Unevaluated generic const parameters are making their way through monomorphization and into symbol mangling, which should definitely be fixed.

Passing -Zsymbol-mangling-version=v0 also fixes the linker error in my issue.

@BoxyUwU
Copy link
Member

BoxyUwU commented Jun 28, 2022

#![feature(generic_const_exprs)]

pub trait Foo {
    fn foo(&self);
}

pub struct FooImpl<const N: usize>;
impl<const N: usize> Foo for FooImpl<N> {
    fn foo(&self) {}
}

pub trait Bar: 'static {
    type Foo: Foo;
    fn get() -> &'static Self::Foo;
}

struct BarImpl;
impl Bar for BarImpl {
    type Foo = FooImpl<{{ 4 }}>;
    fn get() -> &'static Self::Foo {
        &FooImpl
    }
}

pub fn boom<B: Bar>() {
    B::get().foo();
}

fn main() {
    boom::<BarImpl>();
}

still an issue but the repro is slightly different (added some {} around { 4 } and updated feature gate)

@lcnr
Copy link
Contributor

lcnr commented Jun 28, 2022

It seems that Unevaluated generic const parameters are making their way though monomorphization and into symbol mangling, which should definitely be fixed.

jup, should definitely be fixed

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
A-const-generics Area: const generics (parameters and arguments) A-linkage Area: linking into static, shared libraries and binaries C-bug Category: This is a bug. F-generic_const_exprs `#![feature(generic_const_exprs)]` T-compiler Relevant to the compiler team, which will review and decide on the PR/issue.
Projects
None yet
7 participants