Skip to content

Functions pointers with associated type parameters can't cast to pointers #54094

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

Closed
michaelwu opened this issue Sep 10, 2018 · 5 comments · Fixed by #70982
Closed

Functions pointers with associated type parameters can't cast to pointers #54094

michaelwu opened this issue Sep 10, 2018 · 5 comments · Fixed by #70982
Labels
A-associated-items Area: Associated items (types, constants & functions) A-coercions Area: implicit and explicit `expr as Type` coercions C-bug Category: This is a bug. T-compiler Relevant to the compiler team, which will review and decide on the PR/issue.

Comments

@michaelwu
Copy link
Contributor

trait Zoo {
    type X;
}

impl Zoo for u16 {
    type X = usize;
}

fn foo(abc: <u16 as Zoo>::X) {}

fn main() {
    let x: *const u8 = foo as _;
}

(Playground)

Errors:

   Compiling playground v0.0.1 (file:///playground)
error[E0605]: non-primitive cast: `fn(<u16 as Zoo>::X) {foo}` as `*const u8`
  --> src/main.rs:13:24
   |
13 |     let x: *const u8 = foo as _;
   |                        ^^^^^^^^
   |
   = note: an `as` expression can only be used to convert between primitive types. Consider using the `From` trait

error: aborting due to previous error

For more information about this error, try `rustc --explain E0605`.
error: Could not compile `playground`.

To learn more, run the command again with --verbose.

Seems like this should work.

@michaelwu michaelwu changed the title Functions pointers with associated constant parameters can't cast to pointers Functions pointers with associated type parameters can't cast to pointers Sep 10, 2018
@Havvy
Copy link
Contributor

Havvy commented Sep 10, 2018

The following works:

  • Switching abc to be of type usize itself.
  • Adding type X = usize, and then switching abc to be of type X

@eddyb
Copy link
Member

eddyb commented Sep 10, 2018

Huh, what if you cast it to fn(_)? That works, right?

@michaelwu
Copy link
Contributor Author

Adding an intermediate cast to fn(_) does make it work. Playground

@eddyb
Copy link
Member

eddyb commented Sep 10, 2018

So having a projection in the type, blocks the cast from happening? That's a bit weird.
cc @nikomatsakis @arielb1

@arielb1
Copy link
Contributor

arielb1 commented Sep 17, 2018

The fn_sig function on fn item types is returning unnormalized types directly from the tcx.

Defined in

rust/src/librustc/ty/sty.rs

Lines 1739 to 1747 in f1aefb4

pub fn fn_sig(&self, tcx: TyCtxt<'a, 'gcx, 'tcx>) -> PolyFnSig<'tcx> {
match self.sty {
FnDef(def_id, substs) => {
tcx.fn_sig(def_id).subst(tcx, substs)
}
FnPtr(f) => f,
_ => bug!("Ty::fn_sig() called on non-fn type: {:?}", self)
}
}

The relevant call-site is at

if let ty::FnDef(..) = self.expr_ty.sty {
// Attempt a coercion to a fn pointer type.
let f = self.expr_ty.fn_sig(fcx.tcx);
let res = fcx.try_coerce(self.expr,
self.expr_ty,
fcx.tcx.mk_fn_ptr(f),
AllowTwoPhase::No);
if !res.is_ok() {
return Err(CastError::NonScalar);
}
(FnPtr, t_cast)
} else {

@jonas-schievink jonas-schievink added A-associated-items Area: Associated items (types, constants & functions) T-compiler Relevant to the compiler team, which will review and decide on the PR/issue. C-bug Category: This is a bug. A-coercions Area: implicit and explicit `expr as Type` coercions labels Jan 27, 2019
Dylan-DPC-zz pushed a commit to Dylan-DPC-zz/rust that referenced this issue Apr 10, 2020
Normalize function signature in function casting check procedure

Fixes rust-lang#54094
```rust
trait Zoo {
    type X;
}

impl Zoo for u16 {
    type X = usize;
}

fn foo(abc: <u16 as Zoo>::X) {}

fn main() {
    let x: *const u8 = foo as _;
}
```

Currently a `FnDef` need to be checked if it's able to cast to `FnPtr` before it is actually casted. But the signature of `FnPtr` target's associated types are not normalized:

https://github.com/rust-lang/rust/blob/96d77f0e5f103612d62b85938aacfb33f5768433/src/librustc_typeck/check/cast.rs#L536-L553
However, during the coercion check, the signature of `FnPtr` target's associated types are normalized (The `<u16 as Zoo>::X` turns into `usize`).

https://github.com/rust-lang/rust/blob/96d77f0e5f103612d62b85938aacfb33f5768433/src/librustc_typeck/check/coercion.rs#L687-L729

This inconsistency leads to the error:`Err(Sorts(ExpectedFound { expected: <u16 as Zoo>::X, found: usize }))`.
@bors bors closed this as completed in 0a6d177 Apr 11, 2020
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
A-associated-items Area: Associated items (types, constants & functions) A-coercions Area: implicit and explicit `expr as Type` coercions C-bug Category: This is a bug. T-compiler Relevant to the compiler team, which will review and decide on the PR/issue.
Projects
None yet
Development

Successfully merging a pull request may close this issue.

5 participants