mirror of
https://github.com/rust-lang/rust.git
synced 2025-02-23 04:14:28 +00:00
fix incorrect param env in dead code lint
This commit is contained in:
parent
b95852b93c
commit
b92c2f792c
@ -242,7 +242,9 @@ impl<'tcx> MarkSymbolVisitor<'tcx> {
|
|||||||
let &(container, ref indices) =
|
let &(container, ref indices) =
|
||||||
data.get(expr.hir_id).expect("no offset_of_data for offset_of");
|
data.get(expr.hir_id).expect("no offset_of_data for offset_of");
|
||||||
|
|
||||||
let mut last_did = expr.hir_id.owner.to_def_id();
|
let body_did = self.typeck_results().hir_owner.to_def_id();
|
||||||
|
let param_env = self.tcx.param_env(body_did);
|
||||||
|
|
||||||
let mut current_ty = container;
|
let mut current_ty = container;
|
||||||
|
|
||||||
for &index in indices {
|
for &index in indices {
|
||||||
@ -253,15 +255,14 @@ impl<'tcx> MarkSymbolVisitor<'tcx> {
|
|||||||
self.insert_def_id(field.did);
|
self.insert_def_id(field.did);
|
||||||
let field_ty = field.ty(self.tcx, subst);
|
let field_ty = field.ty(self.tcx, subst);
|
||||||
|
|
||||||
last_did = field.did;
|
|
||||||
current_ty =
|
current_ty =
|
||||||
self.tcx.normalize_erasing_regions(self.tcx.param_env(field.did), field_ty);
|
self.tcx.normalize_erasing_regions(param_env, field_ty);
|
||||||
}
|
}
|
||||||
// we don't need to mark tuple fields as live,
|
// we don't need to mark tuple fields as live,
|
||||||
// but we may need to mark subfields
|
// but we may need to mark subfields
|
||||||
ty::Tuple(tys) => {
|
ty::Tuple(tys) => {
|
||||||
current_ty = self.tcx.normalize_erasing_regions(
|
current_ty = self.tcx.normalize_erasing_regions(
|
||||||
self.tcx.param_env(last_did),
|
param_env,
|
||||||
tys[index.as_usize()],
|
tys[index.as_usize()],
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -458,4 +458,4 @@ fn offset_of_addr() {
|
|||||||
assert_eq!(ptr::addr_of!(base).addr() + offset_of!(Foo, y), ptr::addr_of!(base.y).addr());
|
assert_eq!(ptr::addr_of!(base).addr() + offset_of!(Foo, y), ptr::addr_of!(base.y).addr());
|
||||||
assert_eq!(ptr::addr_of!(base).addr() + offset_of!(Foo, z.0), ptr::addr_of!(base.z.0).addr());
|
assert_eq!(ptr::addr_of!(base).addr() + offset_of!(Foo, z.0), ptr::addr_of!(base.z.0).addr());
|
||||||
assert_eq!(ptr::addr_of!(base).addr() + offset_of!(Foo, z.1), ptr::addr_of!(base.z.1).addr());
|
assert_eq!(ptr::addr_of!(base).addr() + offset_of!(Foo, z.1), ptr::addr_of!(base.z.1).addr());
|
||||||
}
|
}
|
40
tests/ui/lint/dead-code/offset-of-correct-param-env.rs
Normal file
40
tests/ui/lint/dead-code/offset-of-correct-param-env.rs
Normal file
@ -0,0 +1,40 @@
|
|||||||
|
// check-pass
|
||||||
|
|
||||||
|
#![feature(offset_of)]
|
||||||
|
#![deny(dead_code)]
|
||||||
|
|
||||||
|
// This struct contains a projection that can only be normalized after getting the field type.
|
||||||
|
struct A<T: Project> {
|
||||||
|
a: <T as Project>::EquateParamTo,
|
||||||
|
}
|
||||||
|
|
||||||
|
// This is the inner struct that we want to get.
|
||||||
|
struct MyFieldIsNotDead {
|
||||||
|
not_dead: u8,
|
||||||
|
}
|
||||||
|
|
||||||
|
// These are some helpers.
|
||||||
|
// Inside the param env of `test`, we want to make it so that it considers T=MyFieldIsNotDead.
|
||||||
|
struct GenericIsEqual<T>(T);
|
||||||
|
trait Project {
|
||||||
|
type EquateParamTo;
|
||||||
|
}
|
||||||
|
impl<T> Project for GenericIsEqual<T> {
|
||||||
|
type EquateParamTo = T;
|
||||||
|
}
|
||||||
|
|
||||||
|
fn test<T>() -> usize
|
||||||
|
where
|
||||||
|
GenericIsEqual<T>: Project<EquateParamTo = MyFieldIsNotDead>,
|
||||||
|
{
|
||||||
|
// The first field of the A that we construct here is `<GenericIsEqual<T>> as Project>::EquateParamTo`.
|
||||||
|
// Typeck normalizes this and figures that the not_dead field is totally fine and accessible.
|
||||||
|
// But importantly, the normalization ends up with T, which, as we've declared in our param env is MyFieldDead.
|
||||||
|
// When we're in the param env of the `a` field, the where bound above is not in scope, so we don't know what T is - it's generic.
|
||||||
|
// We cannot access a field on T. Boom!
|
||||||
|
std::mem::offset_of!(A<GenericIsEqual<T>>, a.not_dead)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn main() {
|
||||||
|
test::<MyFieldIsNotDead>();
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user