Skip to content

Commit ff4b398

Browse files
committed
Auto merge of #127982 - matthiaskrgr:rollup-nzyvphj, r=matthiaskrgr
Rollup of 6 pull requests Successful merges: - #127295 (CFI: Support provided methods on traits) - #127814 (`C-cmse-nonsecure-call`: improved error messages) - #127949 (fix: explain E0120 better cover cases when its raised) - #127966 (Use structured suggestions for unconstrained generic parameters on impl blocks) - #127976 (Lazy type aliases: Diagostics: Detect bivariant ty params that are only used recursively) - #127978 (Avoid ref when using format! for perf) r? `@ghost` `@rustbot` modify labels: rollup
2 parents 0cd01aa + e28be0d commit ff4b398

File tree

28 files changed

+744
-212
lines changed

28 files changed

+744
-212
lines changed

compiler/rustc_error_codes/src/error_codes/E0120.md

+16-8
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
1-
Drop was implemented on a trait, which is not allowed: only structs and
2-
enums can implement Drop.
1+
`Drop` was implemented on a trait object or reference, which is not allowed;
2+
only structs, enums, and unions can implement Drop.
33

4-
Erroneous code example:
4+
Erroneous code examples:
55

66
```compile_fail,E0120
77
trait MyTrait {}
@@ -11,8 +11,16 @@ impl Drop for MyTrait {
1111
}
1212
```
1313

14-
A workaround for this problem is to wrap the trait up in a struct, and implement
15-
Drop on that:
14+
```compile_fail,E0120
15+
struct Concrete {}
16+
17+
impl Drop for &'_ mut Concrete {
18+
fn drop(&mut self) {}
19+
}
20+
```
21+
22+
A workaround for traits is to create a wrapper struct with a generic type,
23+
add a trait bound to the type, and implement `Drop` on the wrapper:
1624

1725
```
1826
trait MyTrait {}
@@ -24,13 +32,13 @@ impl <T: MyTrait> Drop for MyWrapper<T> {
2432
2533
```
2634

27-
Alternatively, wrapping trait objects requires something:
35+
Alternatively, the `Drop` wrapper can contain the trait object:
2836

2937
```
3038
trait MyTrait {}
3139
32-
//or Box<MyTrait>, if you wanted an owned trait object
33-
struct MyWrapper<'a> { foo: &'a MyTrait }
40+
// or Box<dyn MyTrait>, if you wanted an owned trait object
41+
struct MyWrapper<'a> { foo: &'a dyn MyTrait }
3442
3543
impl <'a> Drop for MyWrapper<'a> {
3644
fn drop(&mut self) {}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
Functions marked as `C-cmse-nonsecure-call` place restrictions on their
2+
inputs and outputs.
3+
4+
- inputs must fit in the 4 available 32-bit argument registers. Alignment
5+
is relevant.
6+
- outputs must either fit in 4 bytes, or be a foundational type of
7+
size 8 (`i64`, `u64`, `f64`).
8+
- no generics can be used in the signature
9+
10+
For more information,
11+
see [arm's aapcs32](https://github.com/ARM-software/abi-aa/releases).
12+
13+
Erroneous code example:
14+
15+
```ignore (only fails on supported targets)
16+
#![feature(abi_c_cmse_nonsecure_call)]
17+
18+
#[no_mangle]
19+
pub fn test(
20+
f: extern "C-cmse-nonsecure-call" fn(u32, u32, u32, u32, u32) -> u32,
21+
) -> u32 {
22+
f(1, 2, 3, 4, 5)
23+
}
24+
```
25+
26+
Arguments' alignment is respected. In the example below, padding is inserted
27+
so that the `u64` argument is passed in registers r2 and r3. There is then no
28+
room left for the final `f32` argument
29+
30+
```ignore (only fails on supported targets)
31+
#![feature(abi_c_cmse_nonsecure_call)]
32+
33+
#[no_mangle]
34+
pub fn test(
35+
f: extern "C-cmse-nonsecure-call" fn(u32, u64, f32) -> u32,
36+
) -> u32 {
37+
f(1, 2, 3.0)
38+
}
39+
```

compiler/rustc_error_codes/src/lib.rs

+1
Original file line numberDiff line numberDiff line change
@@ -536,6 +536,7 @@ E0794: 0794,
536536
E0795: 0795,
537537
E0796: 0796,
538538
E0797: 0797,
539+
E0798: 0798,
539540
);
540541
)
541542
}

compiler/rustc_hir_analysis/messages.ftl

+22
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,23 @@ hir_analysis_cannot_capture_late_bound_ty =
5858
hir_analysis_closure_implicit_hrtb = implicit types in closure signatures are forbidden when `for<...>` is present
5959
.label = `for<...>` is here
6060
61+
hir_analysis_cmse_call_generic =
62+
function pointers with the `"C-cmse-nonsecure-call"` ABI cannot contain generics in their type
63+
64+
hir_analysis_cmse_call_inputs_stack_spill =
65+
arguments for `"C-cmse-nonsecure-call"` function too large to pass via registers
66+
.label = {$plural ->
67+
[false] this argument doesn't
68+
*[true] these arguments don't
69+
} fit in the available registers
70+
.note = functions with the `"C-cmse-nonsecure-call"` ABI must pass all their arguments via the 4 32-bit available argument registers
71+
72+
hir_analysis_cmse_call_output_stack_spill =
73+
return value of `"C-cmse-nonsecure-call"` function too large to pass via registers
74+
.label = this type doesn't fit in the available registers
75+
.note1 = functions with the `"C-cmse-nonsecure-call"` ABI must pass their result via the available return registers
76+
.note2 = the result must either be a (transparently wrapped) i64, u64 or f64, or be at most 4 bytes in size
77+
6178
hir_analysis_coerce_unsized_may = the trait `{$trait_name}` may only be implemented for a coercion between structures
6279
6380
hir_analysis_coerce_unsized_multi = implementing the trait `CoerceUnsized` requires multiple coercions
@@ -519,6 +536,11 @@ hir_analysis_typeof_reserved_keyword_used =
519536
.suggestion = consider replacing `typeof(...)` with an actual type
520537
.label = reserved keyword
521538
539+
hir_analysis_unconstrained_generic_parameter = the {$param_def_kind} `{$param_name}` is not constrained by the impl trait, self type, or predicates
540+
.label = unconstrained {$param_def_kind}
541+
.const_param_note = expressions using a const parameter must map each value to a distinct output value
542+
.const_param_note2 = proving the result of expressions other than the parameter are unique is not supported
543+
522544
hir_analysis_unconstrained_opaque_type = unconstrained opaque type
523545
.note = `{$name}` must be used in combination with a concrete type within the same {$what}
524546

compiler/rustc_hir_analysis/src/check/wfcheck.rs

+37-36
Original file line numberDiff line numberDiff line change
@@ -1922,39 +1922,31 @@ fn report_bivariance<'tcx>(
19221922
);
19231923

19241924
if !usage_spans.is_empty() {
1925-
// First, check if the ADT is (probably) cyclical. We say probably here, since
1926-
// we're not actually looking into substitutions, just walking through fields.
1927-
// And we only recurse into the fields of ADTs, and not the hidden types of
1928-
// opaques or anything else fancy.
1925+
// First, check if the ADT/LTA is (probably) cyclical. We say probably here, since we're
1926+
// not actually looking into substitutions, just walking through fields / the "RHS".
1927+
// We don't recurse into the hidden types of opaques or anything else fancy.
19291928
let item_def_id = item.owner_id.to_def_id();
1930-
let is_probably_cyclical = if matches!(
1931-
tcx.def_kind(item_def_id),
1932-
DefKind::Struct | DefKind::Union | DefKind::Enum
1933-
) {
1934-
IsProbablyCyclical { tcx, adt_def_id: item_def_id, seen: Default::default() }
1935-
.visit_all_fields(tcx.adt_def(item_def_id))
1936-
.is_break()
1937-
} else {
1938-
false
1939-
};
1940-
// If the ADT is cyclical, then if at least one usage of the type parameter or
1941-
// the `Self` alias is present in the, then it's probably a cyclical struct, and
1942-
// we should call those parameter usages recursive rather than just saying they're
1943-
// unused...
1929+
let is_probably_cyclical =
1930+
IsProbablyCyclical { tcx, item_def_id, seen: Default::default() }
1931+
.visit_def(item_def_id)
1932+
.is_break();
1933+
// If the ADT/LTA is cyclical, then if at least one usage of the type parameter or
1934+
// the `Self` alias is present in the, then it's probably a cyclical struct/ type
1935+
// alias, and we should call those parameter usages recursive rather than just saying
1936+
// they're unused...
19441937
//
19451938
// We currently report *all* of the parameter usages, since computing the exact
19461939
// subset is very involved, and the fact we're mentioning recursion at all is
19471940
// likely to guide the user in the right direction.
19481941
if is_probably_cyclical {
1949-
let diag = tcx.dcx().create_err(errors::RecursiveGenericParameter {
1942+
return tcx.dcx().emit_err(errors::RecursiveGenericParameter {
19501943
spans: usage_spans,
19511944
param_span: param.span,
19521945
param_name,
19531946
param_def_kind: tcx.def_descr(param.def_id.to_def_id()),
19541947
help,
19551948
note: (),
19561949
});
1957-
return diag.emit();
19581950
}
19591951
}
19601952

@@ -1974,42 +1966,51 @@ fn report_bivariance<'tcx>(
19741966
diag.emit()
19751967
}
19761968

1977-
/// Detects cases where an ADT is trivially cyclical -- we want to detect this so
1978-
/// /we only mention that its parameters are used cyclically if the ADT is truly
1969+
/// Detects cases where an ADT/LTA is trivially cyclical -- we want to detect this so
1970+
/// we only mention that its parameters are used cyclically if the ADT/LTA is truly
19791971
/// cyclical.
19801972
///
19811973
/// Notably, we don't consider substitutions here, so this may have false positives.
19821974
struct IsProbablyCyclical<'tcx> {
19831975
tcx: TyCtxt<'tcx>,
1984-
adt_def_id: DefId,
1976+
item_def_id: DefId,
19851977
seen: FxHashSet<DefId>,
19861978
}
19871979

19881980
impl<'tcx> IsProbablyCyclical<'tcx> {
1989-
fn visit_all_fields(&mut self, adt_def: ty::AdtDef<'tcx>) -> ControlFlow<(), ()> {
1990-
for field in adt_def.all_fields() {
1991-
self.tcx.type_of(field.did).instantiate_identity().visit_with(self)?;
1981+
fn visit_def(&mut self, def_id: DefId) -> ControlFlow<(), ()> {
1982+
match self.tcx.def_kind(def_id) {
1983+
DefKind::Struct | DefKind::Enum | DefKind::Union => {
1984+
self.tcx.adt_def(def_id).all_fields().try_for_each(|field| {
1985+
self.tcx.type_of(field.did).instantiate_identity().visit_with(self)
1986+
})
1987+
}
1988+
DefKind::TyAlias if self.tcx.type_alias_is_lazy(def_id) => {
1989+
self.tcx.type_of(def_id).instantiate_identity().visit_with(self)
1990+
}
1991+
_ => ControlFlow::Continue(()),
19921992
}
1993-
1994-
ControlFlow::Continue(())
19951993
}
19961994
}
19971995

19981996
impl<'tcx> TypeVisitor<TyCtxt<'tcx>> for IsProbablyCyclical<'tcx> {
19991997
type Result = ControlFlow<(), ()>;
20001998

2001-
fn visit_ty(&mut self, t: Ty<'tcx>) -> ControlFlow<(), ()> {
2002-
if let Some(adt_def) = t.ty_adt_def() {
2003-
if adt_def.did() == self.adt_def_id {
1999+
fn visit_ty(&mut self, ty: Ty<'tcx>) -> ControlFlow<(), ()> {
2000+
let def_id = match ty.kind() {
2001+
ty::Adt(adt_def, _) => Some(adt_def.did()),
2002+
ty::Alias(ty::Weak, alias_ty) => Some(alias_ty.def_id),
2003+
_ => None,
2004+
};
2005+
if let Some(def_id) = def_id {
2006+
if def_id == self.item_def_id {
20042007
return ControlFlow::Break(());
20052008
}
2006-
2007-
if self.seen.insert(adt_def.did()) {
2008-
self.visit_all_fields(adt_def)?;
2009+
if self.seen.insert(def_id) {
2010+
self.visit_def(def_id)?;
20092011
}
20102012
}
2011-
2012-
t.super_visit_with(self)
2013+
ty.super_visit_with(self)
20132014
}
20142015
}
20152016

compiler/rustc_hir_analysis/src/errors.rs

+41
Original file line numberDiff line numberDiff line change
@@ -1604,6 +1604,20 @@ pub(crate) enum UnusedGenericParameterHelp {
16041604
TyAlias { param_name: Ident },
16051605
}
16061606

1607+
#[derive(Diagnostic)]
1608+
#[diag(hir_analysis_unconstrained_generic_parameter)]
1609+
pub(crate) struct UnconstrainedGenericParameter {
1610+
#[primary_span]
1611+
#[label]
1612+
pub span: Span,
1613+
pub param_name: Symbol,
1614+
pub param_def_kind: &'static str,
1615+
#[note(hir_analysis_const_param_note)]
1616+
pub const_param_note: Option<()>,
1617+
#[note(hir_analysis_const_param_note2)]
1618+
pub const_param_note2: Option<()>,
1619+
}
1620+
16071621
#[derive(Diagnostic)]
16081622
pub enum UnnamedFieldsRepr<'a> {
16091623
#[diag(hir_analysis_unnamed_fields_repr_missing_repr_c)]
@@ -1673,3 +1687,30 @@ pub struct InvalidReceiverTy<'tcx> {
16731687
#[note]
16741688
#[help]
16751689
pub struct EffectsWithoutNextSolver;
1690+
1691+
#[derive(Diagnostic)]
1692+
#[diag(hir_analysis_cmse_call_inputs_stack_spill, code = E0798)]
1693+
#[note]
1694+
pub struct CmseCallInputsStackSpill {
1695+
#[primary_span]
1696+
#[label]
1697+
pub span: Span,
1698+
pub plural: bool,
1699+
}
1700+
1701+
#[derive(Diagnostic)]
1702+
#[diag(hir_analysis_cmse_call_output_stack_spill, code = E0798)]
1703+
#[note(hir_analysis_note1)]
1704+
#[note(hir_analysis_note2)]
1705+
pub struct CmseCallOutputStackSpill {
1706+
#[primary_span]
1707+
#[label]
1708+
pub span: Span,
1709+
}
1710+
1711+
#[derive(Diagnostic)]
1712+
#[diag(hir_analysis_cmse_call_generic, code = E0798)]
1713+
pub struct CmseCallGeneric {
1714+
#[primary_span]
1715+
pub span: Span,
1716+
}

0 commit comments

Comments
 (0)