Skip to content

Commit 9ede7f0

Browse files
Check Sizedness of return type in WF
1 parent 6dd75f0 commit 9ede7f0

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

42 files changed

+451
-394
lines changed

compiler/rustc_hir_analysis/src/check/wfcheck.rs

+28-2
Original file line numberDiff line numberDiff line change
@@ -1061,6 +1061,7 @@ fn check_associated_item(
10611061
let ty = tcx.type_of(item.def_id).instantiate_identity();
10621062
let ty = wfcx.normalize(span, Some(WellFormedLoc::Ty(item_id)), ty);
10631063
wfcx.register_wf_obligation(span, loc, ty.into());
1064+
check_sized_if_body(wfcx, item.def_id.expect_local(), ty, Some(span));
10641065
Ok(())
10651066
}
10661067
ty::AssocKind::Fn => {
@@ -1185,7 +1186,7 @@ fn check_type_defn<'tcx>(
11851186
),
11861187
wfcx.param_env,
11871188
ty,
1188-
tcx.require_lang_item(LangItem::Sized, None),
1189+
tcx.require_lang_item(LangItem::Sized, Some(hir_ty.span)),
11891190
);
11901191
}
11911192

@@ -1312,7 +1313,7 @@ fn check_item_type(
13121313
),
13131314
wfcx.param_env,
13141315
item_ty,
1315-
tcx.require_lang_item(LangItem::Sized, None),
1316+
tcx.require_lang_item(LangItem::Sized, Some(ty_span)),
13161317
);
13171318
}
13181319

@@ -1642,6 +1643,31 @@ fn check_fn_or_method<'tcx>(
16421643
);
16431644
}
16441645
}
1646+
1647+
// If the function has a body, additionally require that the return type is sized.
1648+
check_sized_if_body(wfcx, def_id, sig.output(), match hir_decl.output {
1649+
hir::FnRetTy::Return(ty) => Some(ty.span),
1650+
hir::FnRetTy::DefaultReturn(_) => None,
1651+
});
1652+
}
1653+
1654+
fn check_sized_if_body<'tcx>(
1655+
wfcx: &WfCheckingCtxt<'_, 'tcx>,
1656+
def_id: LocalDefId,
1657+
ty: Ty<'tcx>,
1658+
maybe_span: Option<Span>,
1659+
) {
1660+
let tcx = wfcx.tcx();
1661+
if let Some(body) = tcx.hir().maybe_body_owned_by(def_id) {
1662+
let span = maybe_span.unwrap_or(body.value.span);
1663+
1664+
wfcx.register_bound(
1665+
ObligationCause::new(span, def_id, traits::ObligationCauseCode::SizedReturnType),
1666+
wfcx.param_env,
1667+
ty,
1668+
tcx.require_lang_item(LangItem::Sized, Some(span)),
1669+
);
1670+
}
16451671
}
16461672

16471673
/// The `arbitrary_self_types_pointers` feature implies `arbitrary_self_types`.

compiler/rustc_hir_typeck/src/check.rs

+1-6
Original file line numberDiff line numberDiff line change
@@ -122,12 +122,7 @@ pub(super) fn check_fn<'a, 'tcx>(
122122
hir::FnRetTy::Return(ty) => ty.span,
123123
};
124124

125-
fcx.require_type_is_sized(
126-
declared_ret_ty,
127-
return_or_body_span,
128-
ObligationCauseCode::SizedReturnType,
129-
);
130-
// We checked the root's signature during wfcheck, but not the child.
125+
// We checked the root's ret ty during wfcheck, but not the child.
131126
if fcx.tcx.is_typeck_child(fn_def_id.to_def_id()) {
132127
fcx.require_type_is_sized(
133128
declared_ret_ty,

compiler/rustc_hir_typeck/src/lib.rs

-2
Original file line numberDiff line numberDiff line change
@@ -186,8 +186,6 @@ fn typeck_with_inspect<'tcx>(
186186
let wf_code = ObligationCauseCode::WellFormed(Some(WellFormedLoc::Ty(def_id)));
187187
fcx.register_wf_obligation(expected_type.into(), body.value.span, wf_code);
188188

189-
fcx.require_type_is_sized(expected_type, body.value.span, ObligationCauseCode::ConstSized);
190-
191189
// Gather locals in statics (because of block expressions).
192190
GatherLocalsVisitor::new(&fcx).visit_body(body);
193191

compiler/rustc_trait_selection/src/error_reporting/traits/fulfillment_errors.rs

-5
Original file line numberDiff line numberDiff line change
@@ -715,7 +715,6 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
715715
};
716716

717717
self.note_obligation_cause(&mut err, &obligation);
718-
self.point_at_returns_when_relevant(&mut err, &obligation);
719718
err.emit()
720719
}
721720
}
@@ -815,7 +814,6 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
815814
"Async",
816815
);
817816
self.note_obligation_cause(&mut err, &obligation);
818-
self.point_at_returns_when_relevant(&mut err, &obligation);
819817
return Some(err.emit());
820818
}
821819
}
@@ -861,7 +859,6 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
861859
"",
862860
);
863861
self.note_obligation_cause(&mut err, &obligation);
864-
self.point_at_returns_when_relevant(&mut err, &obligation);
865862
return Some(err.emit());
866863
}
867864

@@ -877,7 +874,6 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
877874
kind: expected_kind.as_str(),
878875
});
879876
self.note_obligation_cause(&mut err, &obligation);
880-
self.point_at_returns_when_relevant(&mut err, &obligation);
881877
return Some(err.emit());
882878
}
883879
}
@@ -2846,7 +2842,6 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
28462842
err.span_note(self.tcx.def_span(def_id), "opaque type is declared here");
28472843

28482844
self.note_obligation_cause(&mut err, &obligation);
2849-
self.point_at_returns_when_relevant(&mut err, &obligation);
28502845
self.dcx().try_steal_replace_and_emit_err(self.tcx.def_span(def_id), StashKey::Cycle, err)
28512846
}
28522847

compiler/rustc_trait_selection/src/error_reporting/traits/overflow.rs

-1
Original file line numberDiff line numberDiff line change
@@ -196,7 +196,6 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
196196
suggest_increasing_limit,
197197
);
198198
self.note_obligation_cause(&mut err, &obligation);
199-
self.point_at_returns_when_relevant(&mut err, &obligation);
200199
err.emit()
201200
}
202201
}

compiler/rustc_trait_selection/src/error_reporting/traits/suggestions.rs

+8-55
Original file line numberDiff line numberDiff line change
@@ -1788,25 +1788,13 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
17881788
} else {
17891789
("dyn ", span.shrink_to_lo())
17901790
};
1791-
let alternatively = if visitor
1792-
.returns
1793-
.iter()
1794-
.map(|expr| self.typeck_results.as_ref().unwrap().expr_ty_adjusted_opt(expr))
1795-
.collect::<FxHashSet<_>>()
1796-
.len()
1797-
<= 1
1798-
{
1799-
err.span_suggestion_verbose(
1800-
impl_span,
1801-
"consider returning an `impl Trait` instead of a `dyn Trait`",
1802-
"impl ",
1803-
Applicability::MaybeIncorrect,
1804-
);
1805-
"alternatively, "
1806-
} else {
1807-
err.help("if there were a single returned type, you could use `impl Trait` instead");
1808-
""
1809-
};
1791+
1792+
err.span_suggestion_verbose(
1793+
impl_span,
1794+
"consider returning an `impl Trait` instead of a `dyn Trait`",
1795+
"impl ",
1796+
Applicability::MaybeIncorrect,
1797+
);
18101798

18111799
let mut sugg = vec![
18121800
(span.shrink_to_lo(), format!("Box<{pre}")),
@@ -1838,7 +1826,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
18381826

18391827
err.multipart_suggestion(
18401828
format!(
1841-
"{alternatively}box the return type, and wrap all of the returned values in \
1829+
"alternatively, box the return type, and wrap all of the returned values in \
18421830
`Box::new`",
18431831
),
18441832
sugg,
@@ -1848,41 +1836,6 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
18481836
true
18491837
}
18501838

1851-
pub(super) fn point_at_returns_when_relevant(
1852-
&self,
1853-
err: &mut Diag<'_>,
1854-
obligation: &PredicateObligation<'tcx>,
1855-
) {
1856-
match obligation.cause.code().peel_derives() {
1857-
ObligationCauseCode::SizedReturnType => {}
1858-
_ => return,
1859-
}
1860-
1861-
let hir = self.tcx.hir();
1862-
let node = self.tcx.hir_node_by_def_id(obligation.cause.body_id);
1863-
if let hir::Node::Item(hir::Item {
1864-
kind: hir::ItemKind::Fn { body: body_id, .. }, ..
1865-
}) = node
1866-
{
1867-
let body = hir.body(*body_id);
1868-
// Point at all the `return`s in the function as they have failed trait bounds.
1869-
let mut visitor = ReturnsVisitor::default();
1870-
visitor.visit_body(body);
1871-
let typeck_results = self.typeck_results.as_ref().unwrap();
1872-
for expr in &visitor.returns {
1873-
if let Some(returned_ty) = typeck_results.node_type_opt(expr.hir_id) {
1874-
let ty = self.resolve_vars_if_possible(returned_ty);
1875-
if ty.references_error() {
1876-
// don't print out the [type error] here
1877-
err.downgrade_to_delayed_bug();
1878-
} else {
1879-
err.span_label(expr.span, format!("this returned value is of type `{ty}`"));
1880-
}
1881-
}
1882-
}
1883-
}
1884-
}
1885-
18861839
pub(super) fn report_closure_arg_mismatch(
18871840
&self,
18881841
span: Span,

tests/crashes/134355.rs

-6
This file was deleted.

tests/ui/associated-consts/issue-58022.stderr

+9-9
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,3 @@
1-
error[E0790]: cannot refer to the associated constant on trait without specifying the corresponding `impl` type
2-
--> $DIR/issue-58022.rs:4:25
3-
|
4-
LL | const SIZE: usize;
5-
| ------------------ `Foo::SIZE` defined here
6-
LL |
7-
LL | fn new(slice: &[u8; Foo::SIZE]) -> Self;
8-
| ^^^^^^^^^ cannot refer to the associated constant of trait
9-
101
error[E0277]: the size for values of type `[u8]` cannot be known at compilation time
112
--> $DIR/issue-58022.rs:13:41
123
|
@@ -21,6 +12,15 @@ LL | pub struct Bar<T: ?Sized>(T);
2112
| ^^^
2213
= note: the return type of a function must have a statically known size
2314

15+
error[E0790]: cannot refer to the associated constant on trait without specifying the corresponding `impl` type
16+
--> $DIR/issue-58022.rs:4:25
17+
|
18+
LL | const SIZE: usize;
19+
| ------------------ `Foo::SIZE` defined here
20+
LL |
21+
LL | fn new(slice: &[u8; Foo::SIZE]) -> Self;
22+
| ^^^^^^^^^ cannot refer to the associated constant of trait
23+
2424
error[E0423]: expected function, tuple struct or tuple variant, found trait `Foo`
2525
--> $DIR/issue-58022.rs:15:9
2626
|

tests/ui/consts/const-slice-array-deref.rs

-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
11
const ONE: [u16] = [1];
22
//~^ ERROR the size for values of type `[u16]` cannot be known at compilation time
3-
//~| ERROR the size for values of type `[u16]` cannot be known at compilation time
43
//~| ERROR mismatched types
54

65
const TWO: &'static u16 = &ONE[0];

tests/ui/consts/const-slice-array-deref.stderr

+2-11
Original file line numberDiff line numberDiff line change
@@ -12,22 +12,13 @@ error[E0308]: mismatched types
1212
LL | const ONE: [u16] = [1];
1313
| ^^^ expected `[u16]`, found `[u16; 1]`
1414

15-
error[E0277]: the size for values of type `[u16]` cannot be known at compilation time
16-
--> $DIR/const-slice-array-deref.rs:1:20
17-
|
18-
LL | const ONE: [u16] = [1];
19-
| ^^^ doesn't have a size known at compile-time
20-
|
21-
= help: the trait `Sized` is not implemented for `[u16]`
22-
= note: constant expressions must have a statically known size
23-
2415
error[E0161]: cannot move a value of type `[u16]`
25-
--> $DIR/const-slice-array-deref.rs:6:28
16+
--> $DIR/const-slice-array-deref.rs:5:28
2617
|
2718
LL | const TWO: &'static u16 = &ONE[0];
2819
| ^^^ the size of `[u16]` cannot be statically determined
2920

30-
error: aborting due to 4 previous errors
21+
error: aborting due to 3 previous errors
3122

3223
Some errors have detailed explanations: E0161, E0277, E0308.
3324
For more information about an error, try `rustc --explain E0161`.

tests/ui/consts/const-unsized.rs

+4-4
Original file line numberDiff line numberDiff line change
@@ -2,19 +2,19 @@ use std::fmt::Debug;
22

33
const CONST_0: dyn Debug + Sync = *(&0 as &(dyn Debug + Sync));
44
//~^ ERROR the size for values of type
5-
//~| ERROR the size for values of type
5+
//~| ERROR cannot move out of a shared reference
66

77
const CONST_FOO: str = *"foo";
88
//~^ ERROR the size for values of type
9-
//~| ERROR the size for values of type
9+
//~| ERROR cannot move out of a shared reference
1010

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

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

1919
fn main() {
2020
println!("{:?} {:?} {:?} {:?}", &CONST_0, &CONST_FOO, &STATIC_1, &STATIC_BAR);

tests/ui/consts/const-unsized.stderr

+21-33
Original file line numberDiff line numberDiff line change
@@ -6,15 +6,6 @@ LL | const CONST_0: dyn Debug + Sync = *(&0 as &(dyn Debug + Sync));
66
|
77
= help: the trait `Sized` is not implemented for `(dyn Debug + Sync + 'static)`
88

9-
error[E0277]: the size for values of type `(dyn Debug + Sync + 'static)` cannot be known at compilation time
10-
--> $DIR/const-unsized.rs:3:35
11-
|
12-
LL | const CONST_0: dyn Debug + Sync = *(&0 as &(dyn Debug + Sync));
13-
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time
14-
|
15-
= help: the trait `Sized` is not implemented for `(dyn Debug + Sync + 'static)`
16-
= note: constant expressions must have a statically known size
17-
189
error[E0277]: the size for values of type `str` cannot be known at compilation time
1910
--> $DIR/const-unsized.rs:7:18
2011
|
@@ -23,15 +14,6 @@ LL | const CONST_FOO: str = *"foo";
2314
|
2415
= help: the trait `Sized` is not implemented for `str`
2516

26-
error[E0277]: the size for values of type `str` cannot be known at compilation time
27-
--> $DIR/const-unsized.rs:7:24
28-
|
29-
LL | const CONST_FOO: str = *"foo";
30-
| ^^^^^^ doesn't have a size known at compile-time
31-
|
32-
= help: the trait `Sized` is not implemented for `str`
33-
= note: constant expressions must have a statically known size
34-
3517
error[E0277]: the size for values of type `(dyn Debug + Sync + 'static)` cannot be known at compilation time
3618
--> $DIR/const-unsized.rs:11:18
3719
|
@@ -40,15 +22,6 @@ LL | static STATIC_1: dyn Debug + Sync = *(&1 as &(dyn Debug + Sync));
4022
|
4123
= help: the trait `Sized` is not implemented for `(dyn Debug + Sync + 'static)`
4224

43-
error[E0277]: the size for values of type `(dyn Debug + Sync + 'static)` cannot be known at compilation time
44-
--> $DIR/const-unsized.rs:11:37
45-
|
46-
LL | static STATIC_1: dyn Debug + Sync = *(&1 as &(dyn Debug + Sync));
47-
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time
48-
|
49-
= help: the trait `Sized` is not implemented for `(dyn Debug + Sync + 'static)`
50-
= note: constant expressions must have a statically known size
51-
5225
error[E0277]: the size for values of type `str` cannot be known at compilation time
5326
--> $DIR/const-unsized.rs:15:20
5427
|
@@ -57,14 +30,29 @@ LL | static STATIC_BAR: str = *"bar";
5730
|
5831
= help: the trait `Sized` is not implemented for `str`
5932

60-
error[E0277]: the size for values of type `str` cannot be known at compilation time
33+
error[E0507]: cannot move out of a shared reference
34+
--> $DIR/const-unsized.rs:3:35
35+
|
36+
LL | const CONST_0: dyn Debug + Sync = *(&0 as &(dyn Debug + Sync));
37+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ move occurs because value has type `dyn Debug + Sync`, which does not implement the `Copy` trait
38+
39+
error[E0507]: cannot move out of a shared reference
40+
--> $DIR/const-unsized.rs:7:24
41+
|
42+
LL | const CONST_FOO: str = *"foo";
43+
| ^^^^^^ move occurs because value has type `str`, which does not implement the `Copy` trait
44+
45+
error[E0507]: cannot move out of a shared reference
46+
--> $DIR/const-unsized.rs:11:37
47+
|
48+
LL | static STATIC_1: dyn Debug + Sync = *(&1 as &(dyn Debug + Sync));
49+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ move occurs because value has type `dyn Debug + Sync`, which does not implement the `Copy` trait
50+
51+
error[E0507]: cannot move out of a shared reference
6152
--> $DIR/const-unsized.rs:15:26
6253
|
6354
LL | static STATIC_BAR: str = *"bar";
64-
| ^^^^^^ doesn't have a size known at compile-time
65-
|
66-
= help: the trait `Sized` is not implemented for `str`
67-
= note: constant expressions must have a statically known size
55+
| ^^^^^^ move occurs because value has type `str`, which does not implement the `Copy` trait
6856

6957
error[E0161]: cannot move a value of type `str`
7058
--> $DIR/const-unsized.rs:20:48
@@ -80,5 +68,5 @@ LL | println!("{:?} {:?} {:?} {:?}", &CONST_0, &CONST_FOO, &STATIC_1, &STATI
8068

8169
error: aborting due to 10 previous errors
8270

83-
Some errors have detailed explanations: E0161, E0277.
71+
Some errors have detailed explanations: E0161, E0277, E0507.
8472
For more information about an error, try `rustc --explain E0161`.

0 commit comments

Comments
 (0)