Skip to content

Commit 8095c2d

Browse files
committed
Check statics' type in type_of.
1 parent ec81464 commit 8095c2d

29 files changed

+125
-288
lines changed

compiler/rustc_hir_analysis/src/check/check.rs

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -767,7 +767,6 @@ pub(crate) fn check_item_type(tcx: TyCtxt<'_>, def_id: LocalDefId) -> Result<(),
767767
DefKind::Static { .. } => {
768768
check_static_inhabited(tcx, def_id);
769769
check_static_linkage(tcx, def_id);
770-
res = res.and(wfcheck::check_static_item(tcx, def_id));
771770
}
772771
DefKind::Const => res = res.and(wfcheck::check_const_item(tcx, def_id)),
773772
_ => unreachable!(),

compiler/rustc_hir_analysis/src/check/wfcheck.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1180,12 +1180,12 @@ fn check_item_fn(
11801180
}
11811181

11821182
#[instrument(level = "debug", skip(tcx))]
1183-
pub(super) fn check_static_item(
1184-
tcx: TyCtxt<'_>,
1183+
pub(crate) fn check_static_item<'tcx>(
1184+
tcx: TyCtxt<'tcx>,
11851185
item_id: LocalDefId,
1186+
ty: Ty<'tcx>,
11861187
) -> Result<(), ErrorGuaranteed> {
11871188
enter_wf_checking_ctxt(tcx, item_id, |wfcx| {
1188-
let ty = tcx.type_of(item_id).instantiate_identity();
11891189
let span = tcx.ty_span(item_id);
11901190
let item_ty = wfcx.deeply_normalize(span, Some(WellFormedLoc::Ty(item_id)), ty);
11911191

compiler/rustc_hir_analysis/src/collect/type_of.rs

Lines changed: 17 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ use rustc_hir::def_id::{DefId, LocalDefId};
55
use rustc_hir::intravisit::VisitorExt;
66
use rustc_hir::{self as hir, AmbigArg, HirId};
77
use rustc_middle::query::plumbing::CyclePlaceholder;
8+
use crate::check::wfcheck::check_static_item;
89
use rustc_middle::ty::print::with_forced_trimmed_paths;
910
use rustc_middle::ty::util::IntTypeExt;
1011
use rustc_middle::ty::{
@@ -217,7 +218,13 @@ pub(super) fn type_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::EarlyBinder<'_
217218
"static variable",
218219
)
219220
} else {
220-
icx.lower_ty(ty)
221+
let ty = icx.lower_ty(ty);
222+
// MIR relies on references to statics being scalars.
223+
// Verify that here to avoid ill-formed MIR.
224+
match check_static_item(tcx, def_id, ty) {
225+
Ok(()) => ty,
226+
Err(guar) => Ty::new_error(tcx, guar),
227+
}
221228
}
222229
}
223230
ItemKind::Const(ident, _, ty, body_id) => {
@@ -275,7 +282,15 @@ pub(super) fn type_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::EarlyBinder<'_
275282
let args = ty::GenericArgs::identity_for_item(tcx, def_id);
276283
Ty::new_fn_def(tcx, def_id.to_def_id(), args)
277284
}
278-
ForeignItemKind::Static(t, _, _) => icx.lower_ty(t),
285+
ForeignItemKind::Static(ty, _, _) => {
286+
let ty = icx.lower_ty(ty);
287+
// MIR relies on references to statics being scalars.
288+
// Verify that here to avoid ill-formed MIR.
289+
match check_static_item(tcx, def_id, ty) {
290+
Ok(()) => ty,
291+
Err(guar) => Ty::new_error(tcx, guar),
292+
}
293+
}
279294
ForeignItemKind::Type => Ty::new_foreign(tcx, def_id.to_def_id()),
280295
},
281296

compiler/rustc_mir_build/src/builder/custom/parse/instruction.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -309,7 +309,7 @@ impl<'a, 'tcx> ParseCtxt<'a, 'tcx> {
309309
| ExprKind::ConstParam { .. }
310310
| ExprKind::ConstBlock { .. } => {
311311
Ok(Operand::Constant(Box::new(
312-
as_constant_inner(self.tcx, self.typing_env, expr, |_| None)
312+
as_constant_inner(expr, |_| None, self.tcx)
313313
)))
314314
},
315315
_ => self.parse_place(expr_id).map(Operand::Copy),
@@ -393,7 +393,7 @@ impl<'a, 'tcx> ParseCtxt<'a, 'tcx> {
393393
| ExprKind::NamedConst { .. }
394394
| ExprKind::NonHirLiteral { .. }
395395
| ExprKind::ConstBlock { .. } => Ok({
396-
let value = as_constant_inner(self.tcx, self.typing_env, expr, |_| None);
396+
let value = as_constant_inner(expr, |_| None, self.tcx);
397397
value.const_.eval_bits(self.tcx, self.typing_env)
398398
}),
399399
)

compiler/rustc_mir_build/src/builder/expr/as_constant.rs

Lines changed: 19 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,14 @@
11
//! See docs in build/expr/mod.rs
22
3-
use rustc_abi::{BackendRepr, Size};
3+
use rustc_abi::Size;
44
use rustc_ast as ast;
55
use rustc_hir::LangItem;
66
use rustc_middle::mir::interpret::{CTFE_ALLOC_SALT, LitToConstInput, Scalar};
77
use rustc_middle::mir::*;
88
use rustc_middle::thir::*;
99
use rustc_middle::ty::{
1010
self, CanonicalUserType, CanonicalUserTypeAnnotation, Ty, TyCtxt, TypeVisitableExt as _,
11-
TypingEnv, UserTypeAnnotationIndex,
11+
UserTypeAnnotationIndex,
1212
};
1313
use rustc_middle::{bug, mir, span_bug};
1414
use tracing::{instrument, trace};
@@ -19,27 +19,32 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
1919
/// Compile `expr`, yielding a compile-time constant. Assumes that
2020
/// `expr` is a valid compile-time constant!
2121
pub(crate) fn as_constant(&mut self, expr: &Expr<'tcx>) -> ConstOperand<'tcx> {
22+
let this = self;
23+
let tcx = this.tcx;
2224
let Expr { ty, temp_lifetime: _, span, ref kind } = *expr;
2325
match kind {
2426
ExprKind::Scope { region_scope: _, lint_level: _, value } => {
25-
self.as_constant(&self.thir[*value])
27+
this.as_constant(&this.thir[*value])
2628
}
27-
_ => as_constant_inner(self.tcx, self.typing_env(), expr, |user_ty| {
28-
Some(self.canonical_user_type_annotations.push(CanonicalUserTypeAnnotation {
29-
span,
30-
user_ty: user_ty.clone(),
31-
inferred_ty: ty,
32-
}))
33-
}),
29+
_ => as_constant_inner(
30+
expr,
31+
|user_ty| {
32+
Some(this.canonical_user_type_annotations.push(CanonicalUserTypeAnnotation {
33+
span,
34+
user_ty: user_ty.clone(),
35+
inferred_ty: ty,
36+
}))
37+
},
38+
tcx,
39+
),
3440
}
3541
}
3642
}
3743

3844
pub(crate) fn as_constant_inner<'tcx>(
39-
tcx: TyCtxt<'tcx>,
40-
typing_env: TypingEnv<'tcx>,
4145
expr: &Expr<'tcx>,
4246
push_cuta: impl FnMut(&Box<CanonicalUserType<'tcx>>) -> Option<UserTypeAnnotationIndex>,
47+
tcx: TyCtxt<'tcx>,
4348
) -> ConstOperand<'tcx> {
4449
let Expr { ty, temp_lifetime: _, span, ref kind } = *expr;
4550
match *kind {
@@ -83,23 +88,8 @@ pub(crate) fn as_constant_inner<'tcx>(
8388
ConstOperand { user_ty: None, span, const_ }
8489
}
8590
ExprKind::StaticRef { alloc_id, ty, .. } => {
86-
let layout = tcx.layout_of(typing_env.as_query_input(ty));
87-
let const_ = if let Ok(layout) = layout
88-
&& let BackendRepr::Scalar(..) = layout.backend_repr
89-
{
90-
let const_val = ConstValue::Scalar(Scalar::from_pointer(alloc_id.into(), &tcx));
91-
Const::Val(const_val, ty)
92-
} else {
93-
// Ill-formed code may produce instances where `pointee` is not `Sized`.
94-
// This should be reported by wfcheck on the static itself.
95-
// Still, producing a single scalar constant would be inconsistent, as pointers to
96-
// non-`Sized` types are scalar pairs. Avoid an ICE by producing an error constant.
97-
let guar = tcx.dcx().span_delayed_bug(
98-
span,
99-
format!("pointer to static's type `{ty}` is not scalar"),
100-
);
101-
Const::Ty(ty, ty::Const::new_error(tcx, guar))
102-
};
91+
let const_val = ConstValue::Scalar(Scalar::from_pointer(alloc_id.into(), &tcx));
92+
let const_ = Const::Val(const_val, ty);
10393

10494
ConstOperand { span, user_ty: None, const_ }
10595
}

tests/ui/consts/const-unsized.rs

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -10,14 +10,10 @@ const CONST_FOO: str = *"foo";
1010

1111
static STATIC_1: dyn Debug + Sync = *(&1 as &(dyn Debug + Sync));
1212
//~^ ERROR the size for values of type
13-
//~| ERROR cannot move out of a shared reference
1413

1514
static STATIC_BAR: str = *"bar";
1615
//~^ ERROR the size for values of type
17-
//~| ERROR cannot move out of a shared reference
1816

1917
fn main() {
2018
println!("{:?} {:?} {:?} {:?}", &CONST_0, &CONST_FOO, &STATIC_1, &STATIC_BAR);
21-
//~^ ERROR: cannot move a value of type `str`
22-
//~| ERROR: cannot move a value of type `dyn Debug + Sync`
2319
}

tests/ui/consts/const-unsized.stderr

Lines changed: 4 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ LL | static STATIC_1: dyn Debug + Sync = *(&1 as &(dyn Debug + Sync));
2626
= note: statics and constants must have a statically known size
2727

2828
error[E0277]: the size for values of type `str` cannot be known at compilation time
29-
--> $DIR/const-unsized.rs:15:1
29+
--> $DIR/const-unsized.rs:14:1
3030
|
3131
LL | static STATIC_BAR: str = *"bar";
3232
| ^^^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time
@@ -46,31 +46,7 @@ error[E0507]: cannot move out of a shared reference
4646
LL | const CONST_FOO: str = *"foo";
4747
| ^^^^^^ move occurs because value has type `str`, which does not implement the `Copy` trait
4848

49-
error[E0507]: cannot move out of a shared reference
50-
--> $DIR/const-unsized.rs:11:37
51-
|
52-
LL | static STATIC_1: dyn Debug + Sync = *(&1 as &(dyn Debug + Sync));
53-
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ move occurs because value has type `dyn Debug + Sync`, which does not implement the `Copy` trait
54-
55-
error[E0507]: cannot move out of a shared reference
56-
--> $DIR/const-unsized.rs:15:26
57-
|
58-
LL | static STATIC_BAR: str = *"bar";
59-
| ^^^^^^ move occurs because value has type `str`, which does not implement the `Copy` trait
60-
61-
error[E0161]: cannot move a value of type `dyn Debug + Sync`
62-
--> $DIR/const-unsized.rs:20:38
63-
|
64-
LL | println!("{:?} {:?} {:?} {:?}", &CONST_0, &CONST_FOO, &STATIC_1, &STATIC_BAR);
65-
| ^^^^^^^ the size of `dyn Debug + Sync` cannot be statically determined
66-
67-
error[E0161]: cannot move a value of type `str`
68-
--> $DIR/const-unsized.rs:20:48
69-
|
70-
LL | println!("{:?} {:?} {:?} {:?}", &CONST_0, &CONST_FOO, &STATIC_1, &STATIC_BAR);
71-
| ^^^^^^^^^ the size of `str` cannot be statically determined
72-
73-
error: aborting due to 10 previous errors
49+
error: aborting due to 6 previous errors
7450

75-
Some errors have detailed explanations: E0161, E0277, E0507.
76-
For more information about an error, try `rustc --explain E0161`.
51+
Some errors have detailed explanations: E0277, E0507.
52+
For more information about an error, try `rustc --explain E0277`.

tests/ui/coroutine/layout-error.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,6 @@ impl<F: Future> Task<F> {
1717
}
1818

1919
pub type F = impl Future;
20-
//~^ ERROR cycle detected when computing type of `F::{opaque#0}`
2120

2221
#[define_opaque(F)]
2322
fn foo()
@@ -33,5 +32,7 @@ where
3332

3433
// Check that statics are inhabited computes they layout.
3534
static POOL: Task<F> = Task::new();
35+
//~^ ERROR cycle detected when computing type of `POOL`
36+
//~| ERROR cycle detected when computing type of `POOL`
3637

3738
fn main() {}
Lines changed: 56 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,55 +1,97 @@
11
error[E0425]: cannot find value `Foo` in this scope
2-
--> $DIR/layout-error.rs:28:17
2+
--> $DIR/layout-error.rs:27:17
33
|
44
LL | let a = Foo;
55
| ^^^ not found in this scope
66

7-
error[E0391]: cycle detected when computing type of `F::{opaque#0}`
8-
--> $DIR/layout-error.rs:19:14
7+
error[E0391]: cycle detected when computing type of `POOL`
8+
--> $DIR/layout-error.rs:34:14
99
|
10-
LL | pub type F = impl Future;
11-
| ^^^^^^^^^^^
10+
LL | static POOL: Task<F> = Task::new();
11+
| ^^^^^^^
1212
|
13+
= note: ...which requires evaluating trait selection obligation `Task<F>: core::marker::Sync`...
1314
note: ...which requires computing type of opaque `F::{opaque#0}`...
1415
--> $DIR/layout-error.rs:19:14
1516
|
1617
LL | pub type F = impl Future;
1718
| ^^^^^^^^^^^
1819
note: ...which requires borrow-checking `foo`...
19-
--> $DIR/layout-error.rs:23:1
20+
--> $DIR/layout-error.rs:22:1
2021
|
2122
LL | / fn foo()
2223
LL | | where
2324
LL | | F:,
2425
| |_______^
2526
note: ...which requires promoting constants in MIR for `foo`...
26-
--> $DIR/layout-error.rs:23:1
27+
--> $DIR/layout-error.rs:22:1
2728
|
2829
LL | / fn foo()
2930
LL | | where
3031
LL | | F:,
3132
| |_______^
3233
note: ...which requires checking if `foo` contains FFI-unwind calls...
33-
--> $DIR/layout-error.rs:23:1
34+
--> $DIR/layout-error.rs:22:1
3435
|
3536
LL | / fn foo()
3637
LL | | where
3738
LL | | F:,
3839
| |_______^
3940
note: ...which requires building MIR for `foo`...
40-
--> $DIR/layout-error.rs:23:1
41+
--> $DIR/layout-error.rs:22:1
42+
|
43+
LL | / fn foo()
44+
LL | | where
45+
LL | | F:,
46+
| |_______^
47+
note: ...which requires match-checking `foo`...
48+
--> $DIR/layout-error.rs:22:1
49+
|
50+
LL | / fn foo()
51+
LL | | where
52+
LL | | F:,
53+
| |_______^
54+
note: ...which requires type-checking `foo`...
55+
--> $DIR/layout-error.rs:22:1
4156
|
4257
LL | / fn foo()
4358
LL | | where
4459
LL | | F:,
4560
| |_______^
46-
= note: ...which requires computing layout of `&Task<F>`...
47-
= note: ...which requires normalizing `&Task<F>`...
48-
= note: ...which again requires computing type of `F::{opaque#0}`, completing the cycle
49-
= note: cycle used when normalizing `Task<F>`
61+
= note: ...which again requires computing type of `POOL`, completing the cycle
62+
note: cycle used when checking that `POOL` is well-formed
63+
--> $DIR/layout-error.rs:34:1
64+
|
65+
LL | static POOL: Task<F> = Task::new();
66+
| ^^^^^^^^^^^^^^^^^^^^
67+
= note: see https://rustc-dev-guide.rust-lang.org/overview.html#queries and https://rustc-dev-guide.rust-lang.org/query.html for more information
68+
69+
error[E0391]: cycle detected when computing type of `POOL`
70+
--> $DIR/layout-error.rs:34:14
71+
|
72+
LL | static POOL: Task<F> = Task::new();
73+
| ^^^^^^^
74+
|
75+
= note: ...which requires evaluating trait selection obligation `Task<F>: core::marker::Sync`...
76+
note: ...which requires computing type of opaque `F::{opaque#0}`...
77+
--> $DIR/layout-error.rs:19:14
78+
|
79+
LL | pub type F = impl Future;
80+
| ^^^^^^^^^^^
81+
note: ...which requires computing the opaque types defined by `POOL`...
82+
--> $DIR/layout-error.rs:34:1
83+
|
84+
LL | static POOL: Task<F> = Task::new();
85+
| ^^^^^^^^^^^^^^^^^^^^
86+
= note: ...which again requires computing type of `POOL`, completing the cycle
87+
note: cycle used when checking that `POOL` is well-formed
88+
--> $DIR/layout-error.rs:34:1
89+
|
90+
LL | static POOL: Task<F> = Task::new();
91+
| ^^^^^^^^^^^^^^^^^^^^
5092
= note: see https://rustc-dev-guide.rust-lang.org/overview.html#queries and https://rustc-dev-guide.rust-lang.org/query.html for more information
5193

52-
error: aborting due to 2 previous errors
94+
error: aborting due to 3 previous errors
5395

5496
Some errors have detailed explanations: E0391, E0425.
5597
For more information about an error, try `rustc --explain E0391`.

tests/ui/coroutine/metadata-sufficient-for-layout.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,6 @@
44
// Regression test for #80998.
55
//
66
//@ aux-build:metadata-sufficient-for-layout.rs
7-
//@ check-pass
87

98
#![feature(type_alias_impl_trait, rustc_attrs)]
109
#![feature(coroutine_trait)]
@@ -23,5 +22,6 @@ mod helper {
2322

2423
// Static queries the layout of the coroutine.
2524
static A: Option<helper::F> = None;
25+
//~^ ERROR cycle detected when computing type of `A`
2626

2727
fn main() {}

0 commit comments

Comments
 (0)