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

Normalize function signature in function casting check procedure #70982

Merged
merged 2 commits into from Apr 11, 2020

Conversation

ldm0
Copy link
Contributor

@ldm0 ldm0 commented Apr 10, 2020

Fixes #54094

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:

match self.expr_ty.kind {
ty::FnDef(..) => {
// 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 let Err(TypeError::IntrinsicCast) = res {
return Err(CastError::IllegalCast);
}
if res.is_err() {
return Err(CastError::NonScalar);
}
(FnPtr, t_cast)
}

However, during the coercion check, the signature of FnPtr target's associated types are normalized (The <u16 as Zoo>::X turns into usize).

fn coerce_from_fn_item(&self, a: Ty<'tcx>, b: Ty<'tcx>) -> CoerceResult<'tcx> {
//! Attempts to coerce from the type of a Rust function item
//! into a closure or a `proc`.
let b = self.shallow_resolve(b);
debug!("coerce_from_fn_item(a={:?}, b={:?})", a, b);
match b.kind {
ty::FnPtr(_) => {
let a_sig = a.fn_sig(self.tcx);
// Intrinsics are not coercible to function pointers
if a_sig.abi() == Abi::RustIntrinsic || a_sig.abi() == Abi::PlatformIntrinsic {
return Err(TypeError::IntrinsicCast);
}
let InferOk { value: a_sig, mut obligations } =
self.normalize_associated_types_in_as_infer_ok(self.cause.span, &a_sig);
let a_fn_pointer = self.tcx.mk_fn_ptr(a_sig);
let InferOk { value, obligations: o2 } = self.coerce_from_safe_fn(
a_fn_pointer,
a_sig,
b,
|unsafe_ty| {
vec![
Adjustment {
kind: Adjust::Pointer(PointerCast::ReifyFnPointer),
target: a_fn_pointer,
},
Adjustment {
kind: Adjust::Pointer(PointerCast::UnsafeFnPointer),
target: unsafe_ty,
},
]
},
simple(Adjust::Pointer(PointerCast::ReifyFnPointer)),
)?;
obligations.extend(o2);
Ok(InferOk { value, obligations })
}
_ => self.unify_and(a, b, identity),
}
}

This inconsistency leads to the error:Err(Sorts(ExpectedFound { expected: <u16 as Zoo>::X, found: usize })).

@rust-highfive
Copy link
Collaborator

r? @ecstatic-morse

(rust_highfive has picked a reviewer for you, use r? to override)

@rust-highfive rust-highfive added the S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. label Apr 10, 2020
@ldm0
Copy link
Contributor Author

ldm0 commented Apr 10, 2020

r? @eddyb
Since 33ecf72

Comment on lines 538 to +542
// Attempt a coercion to a fn pointer type.
let f = self.expr_ty.fn_sig(fcx.tcx);
let f = fcx.normalize_associated_types_in(
self.expr.span,
&self.expr_ty.fn_sig(fcx.tcx),
);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

cc @nikomatsakis This makes sense to me.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, it seems like it is necessary, given that fn_sig returns the result of data from the def_id ..

@eddyb
Copy link
Member

eddyb commented Apr 10, 2020

@bors r+

@bors
Copy link
Contributor

bors commented Apr 10, 2020

📌 Commit 75cc403 has been approved by eddyb

@bors bors added S-waiting-on-bors Status: Waiting on bors to run and complete tests. Bors will change the label on completion. and removed S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. labels Apr 10, 2020
Comment on lines 538 to +542
// Attempt a coercion to a fn pointer type.
let f = self.expr_ty.fn_sig(fcx.tcx);
let f = fcx.normalize_associated_types_in(
self.expr.span,
&self.expr_ty.fn_sig(fcx.tcx),
);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, it seems like it is necessary, given that fn_sig returns the result of data from the def_id ..

Dylan-DPC-zz pushed a commit to Dylan-DPC-zz/rust that referenced this pull request 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 added a commit to rust-lang-ci/rust that referenced this pull request Apr 11, 2020
Rollup of 5 pull requests

Successful merges:

 - rust-lang#69573 (tests encoding current behavior for various cases of "binding" to _.)
 - rust-lang#70881 (bootstrap: work around "unused attribute" errors in incremental stdlib rebuilds.)
 - rust-lang#70957 (Normalize MIR locals' types for generator layout computation.)
 - rust-lang#70962 (added machine hooks to track deallocations)
 - rust-lang#70982 (Normalize function signature in function casting check procedure)

Failed merges:

r? @ghost
@bors bors merged commit 0a6d177 into rust-lang:master Apr 11, 2020
@ldm0 ldm0 deleted the fncoerce branch April 27, 2020 15:26
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
S-waiting-on-bors Status: Waiting on bors to run and complete tests. Bors will change the label on completion.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Functions pointers with associated type parameters can't cast to pointers
6 participants