Skip to content

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

New issue

Have a question about this project? # for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “#”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? # 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
# for free to join this conversation on GitHub. Already have an account? # 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