Skip to content

Commit a2bcfae

Browse files
committed
Auto merge of #134640 - matthiaskrgr:rollup-xlstm3o, r=matthiaskrgr
Rollup of 6 pull requests Successful merges: - #134364 (Use E0665 for missing `#[default]` on enum and update doc) - #134601 (Support pretty-printing `dyn*` trait objects) - #134603 (Explain why a type is not eligible for `impl PointerLike`.) - #134618 (coroutine_clone: add comments) - #134630 (Use `&raw` for `ptr` primitive docs) - #134637 (Flatten effects directory now that it doesn't really test anything specific) r? `@ghost` `@rustbot` modify labels: rollup
2 parents c113247 + 66dbfd4 commit a2bcfae

File tree

54 files changed

+366
-197
lines changed

Some content is hidden

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

54 files changed

+366
-197
lines changed

compiler/rustc_ast_pretty/src/pprust/state.rs

+4-2
Original file line numberDiff line numberDiff line change
@@ -1204,8 +1204,10 @@ impl<'a> State<'a> {
12041204
}
12051205
ast::TyKind::Path(Some(qself), path) => self.print_qpath(path, qself, false),
12061206
ast::TyKind::TraitObject(bounds, syntax) => {
1207-
if *syntax == ast::TraitObjectSyntax::Dyn {
1208-
self.word_nbsp("dyn");
1207+
match syntax {
1208+
ast::TraitObjectSyntax::Dyn => self.word_nbsp("dyn"),
1209+
ast::TraitObjectSyntax::DynStar => self.word_nbsp("dyn*"),
1210+
ast::TraitObjectSyntax::None => {}
12091211
}
12101212
self.print_type_bounds(bounds);
12111213
}

compiler/rustc_builtin_macros/messages.ftl

+3-3
Original file line numberDiff line numberDiff line change
@@ -249,9 +249,9 @@ builtin_macros_naked_functions_testing_attribute =
249249
.label = function marked with testing attribute here
250250
.naked_attribute = `#[naked]` is incompatible with testing attributes
251251
252-
builtin_macros_no_default_variant = no default declared
253-
.help = make a unit variant default by placing `#[default]` above it
254-
.suggestion = make `{$ident}` default
252+
builtin_macros_no_default_variant = `#[derive(Default)]` on enum with no `#[default]`
253+
.label = this enum needs a unit variant marked with `#[default]`
254+
.suggestion = make this unit variant default by placing `#[default]` on it
255255
256256
builtin_macros_non_abi = at least one abi must be provided as an argument to `clobber_abi`
257257

compiler/rustc_builtin_macros/src/deriving/default.rs

+9-4
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,9 @@ pub(crate) fn expand_deriving_default(
4242
StaticStruct(_, fields) => {
4343
default_struct_substructure(cx, trait_span, substr, fields)
4444
}
45-
StaticEnum(enum_def, _) => default_enum_substructure(cx, trait_span, enum_def),
45+
StaticEnum(enum_def, _) => {
46+
default_enum_substructure(cx, trait_span, enum_def, item.span())
47+
}
4648
_ => cx.dcx().span_bug(trait_span, "method in `derive(Default)`"),
4749
}
4850
})),
@@ -96,9 +98,10 @@ fn default_enum_substructure(
9698
cx: &ExtCtxt<'_>,
9799
trait_span: Span,
98100
enum_def: &EnumDef,
101+
item_span: Span,
99102
) -> BlockOrExpr {
100103
let expr = match try {
101-
let default_variant = extract_default_variant(cx, enum_def, trait_span)?;
104+
let default_variant = extract_default_variant(cx, enum_def, trait_span, item_span)?;
102105
validate_default_attribute(cx, default_variant)?;
103106
default_variant
104107
} {
@@ -146,6 +149,7 @@ fn extract_default_variant<'a>(
146149
cx: &ExtCtxt<'_>,
147150
enum_def: &'a EnumDef,
148151
trait_span: Span,
152+
item_span: Span,
149153
) -> Result<&'a rustc_ast::Variant, ErrorGuaranteed> {
150154
let default_variants: SmallVec<[_; 1]> = enum_def
151155
.variants
@@ -163,9 +167,10 @@ fn extract_default_variant<'a>(
163167
.filter(|variant| !attr::contains_name(&variant.attrs, sym::non_exhaustive));
164168

165169
let suggs = possible_defaults
166-
.map(|v| errors::NoDefaultVariantSugg { span: v.span, ident: v.ident })
170+
.map(|v| errors::NoDefaultVariantSugg { span: v.span.shrink_to_lo() })
167171
.collect();
168-
let guar = cx.dcx().emit_err(errors::NoDefaultVariant { span: trait_span, suggs });
172+
let guar =
173+
cx.dcx().emit_err(errors::NoDefaultVariant { span: trait_span, item_span, suggs });
169174

170175
return Err(guar);
171176
}

compiler/rustc_builtin_macros/src/errors.rs

+4-9
Original file line numberDiff line numberDiff line change
@@ -369,26 +369,21 @@ pub(crate) struct DerivePathArgsValue {
369369
}
370370

371371
#[derive(Diagnostic)]
372-
#[diag(builtin_macros_no_default_variant)]
373-
#[help]
372+
#[diag(builtin_macros_no_default_variant, code = E0665)]
374373
pub(crate) struct NoDefaultVariant {
375374
#[primary_span]
376375
pub(crate) span: Span,
376+
#[label]
377+
pub(crate) item_span: Span,
377378
#[subdiagnostic]
378379
pub(crate) suggs: Vec<NoDefaultVariantSugg>,
379380
}
380381

381382
#[derive(Subdiagnostic)]
382-
#[suggestion(
383-
builtin_macros_suggestion,
384-
code = "#[default] {ident}",
385-
applicability = "maybe-incorrect",
386-
style = "tool-only"
387-
)]
383+
#[suggestion(builtin_macros_suggestion, code = "#[default] ", applicability = "maybe-incorrect")]
388384
pub(crate) struct NoDefaultVariantSugg {
389385
#[primary_span]
390386
pub(crate) span: Span,
391-
pub(crate) ident: Ident,
392387
}
393388

394389
#[derive(Diagnostic)]
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,9 @@
1-
#### Note: this error code is no longer emitted by the compiler.
2-
3-
The `Default` trait was derived on an enum.
1+
The `Default` trait was derived on an enum without specifying the default
2+
variant.
43

54
Erroneous code example:
65

7-
```compile_fail
6+
```compile_fail,E0665
87
#[derive(Default)]
98
enum Food {
109
Sweet,
@@ -16,18 +15,30 @@ The `Default` cannot be derived on an enum for the simple reason that the
1615
compiler doesn't know which value to pick by default whereas it can for a
1716
struct as long as all its fields implement the `Default` trait as well.
1817

19-
If you still want to implement `Default` on your enum, you'll have to do it "by
20-
hand":
18+
For the case where the desired default variant has no payload, you can
19+
annotate it with `#[default]` to derive it:
2120

2221
```
22+
#[derive(Default)]
2323
enum Food {
24+
#[default]
2425
Sweet,
2526
Salty,
2627
}
28+
```
29+
30+
In the case where the default variant does have a payload, you will have to
31+
implement `Default` on your enum manually:
32+
33+
```
34+
enum Food {
35+
Sweet(i32),
36+
Salty,
37+
}
2738
2839
impl Default for Food {
2940
fn default() -> Food {
30-
Food::Sweet
41+
Food::Sweet(1)
3142
}
3243
}
3344
```

compiler/rustc_hir_analysis/src/coherence/builtin.rs

+69-31
Original file line numberDiff line numberDiff line change
@@ -673,37 +673,6 @@ fn visit_implementation_of_pointer_like(checker: &Checker<'_>) -> Result<(), Err
673673
let impl_span = tcx.def_span(checker.impl_def_id);
674674
let self_ty = tcx.impl_trait_ref(checker.impl_def_id).unwrap().instantiate_identity().self_ty();
675675

676-
// If an ADT is repr(transparent)...
677-
if let ty::Adt(def, args) = *self_ty.kind()
678-
&& def.repr().transparent()
679-
{
680-
// FIXME(compiler-errors): This should and could be deduplicated into a query.
681-
// Find the nontrivial field.
682-
let adt_typing_env = ty::TypingEnv::non_body_analysis(tcx, def.did());
683-
let nontrivial_field = def.all_fields().find(|field_def| {
684-
let field_ty = tcx.type_of(field_def.did).instantiate_identity();
685-
!tcx.layout_of(adt_typing_env.as_query_input(field_ty))
686-
.is_ok_and(|layout| layout.layout.is_1zst())
687-
});
688-
689-
if let Some(nontrivial_field) = nontrivial_field {
690-
// Check that the nontrivial field implements `PointerLike`.
691-
let nontrivial_field = nontrivial_field.ty(tcx, args);
692-
let (infcx, param_env) = tcx.infer_ctxt().build_with_typing_env(typing_env);
693-
let ocx = ObligationCtxt::new(&infcx);
694-
ocx.register_bound(
695-
ObligationCause::misc(impl_span, checker.impl_def_id),
696-
param_env,
697-
nontrivial_field,
698-
tcx.lang_items().pointer_like().unwrap(),
699-
);
700-
// FIXME(dyn-star): We should regionck this implementation.
701-
if ocx.select_all_or_error().is_empty() {
702-
return Ok(());
703-
}
704-
}
705-
}
706-
707676
let is_permitted_primitive = match *self_ty.kind() {
708677
ty::Adt(def, _) => def.is_box(),
709678
ty::Uint(..) | ty::Int(..) | ty::RawPtr(..) | ty::Ref(..) | ty::FnPtr(..) => true,
@@ -717,12 +686,81 @@ fn visit_implementation_of_pointer_like(checker: &Checker<'_>) -> Result<(), Err
717686
return Ok(());
718687
}
719688

689+
let why_disqualified = match *self_ty.kind() {
690+
// If an ADT is repr(transparent)
691+
ty::Adt(self_ty_def, args) => {
692+
if self_ty_def.repr().transparent() {
693+
// FIXME(compiler-errors): This should and could be deduplicated into a query.
694+
// Find the nontrivial field.
695+
let adt_typing_env = ty::TypingEnv::non_body_analysis(tcx, self_ty_def.did());
696+
let nontrivial_field = self_ty_def.all_fields().find(|field_def| {
697+
let field_ty = tcx.type_of(field_def.did).instantiate_identity();
698+
!tcx.layout_of(adt_typing_env.as_query_input(field_ty))
699+
.is_ok_and(|layout| layout.layout.is_1zst())
700+
});
701+
702+
if let Some(nontrivial_field) = nontrivial_field {
703+
// Check that the nontrivial field implements `PointerLike`.
704+
let nontrivial_field_ty = nontrivial_field.ty(tcx, args);
705+
let (infcx, param_env) = tcx.infer_ctxt().build_with_typing_env(typing_env);
706+
let ocx = ObligationCtxt::new(&infcx);
707+
ocx.register_bound(
708+
ObligationCause::misc(impl_span, checker.impl_def_id),
709+
param_env,
710+
nontrivial_field_ty,
711+
tcx.lang_items().pointer_like().unwrap(),
712+
);
713+
// FIXME(dyn-star): We should regionck this implementation.
714+
if ocx.select_all_or_error().is_empty() {
715+
return Ok(());
716+
} else {
717+
format!(
718+
"the field `{field_name}` of {descr} `{self_ty}` \
719+
does not implement `PointerLike`",
720+
field_name = nontrivial_field.name,
721+
descr = self_ty_def.descr()
722+
)
723+
}
724+
} else {
725+
format!(
726+
"the {descr} `{self_ty}` is `repr(transparent)`, \
727+
but does not have a non-trivial field (it is zero-sized)",
728+
descr = self_ty_def.descr()
729+
)
730+
}
731+
} else if self_ty_def.is_box() {
732+
// If we got here, then the `layout.is_pointer_like()` check failed
733+
// and this box is not a thin pointer.
734+
735+
String::from("boxes of dynamically-sized types are too large to be `PointerLike`")
736+
} else {
737+
format!(
738+
"the {descr} `{self_ty}` is not `repr(transparent)`",
739+
descr = self_ty_def.descr()
740+
)
741+
}
742+
}
743+
ty::Ref(..) => {
744+
// If we got here, then the `layout.is_pointer_like()` check failed
745+
// and this reference is not a thin pointer.
746+
String::from("references to dynamically-sized types are too large to be `PointerLike`")
747+
}
748+
ty::Dynamic(..) | ty::Foreign(..) => {
749+
String::from("types of dynamic or unknown size may not implement `PointerLike`")
750+
}
751+
_ => {
752+
// This is a white lie; it is true everywhere outside the standard library.
753+
format!("only user-defined sized types are eligible for `impl PointerLike`")
754+
}
755+
};
756+
720757
Err(tcx
721758
.dcx()
722759
.struct_span_err(
723760
impl_span,
724761
"implementation must be applied to type that has the same ABI as a pointer, \
725762
or is `repr(transparent)` and whose field is `PointerLike`",
726763
)
764+
.with_note(why_disqualified)
727765
.emit())
728766
}

compiler/rustc_hir_pretty/src/lib.rs

+4-2
Original file line numberDiff line numberDiff line change
@@ -402,8 +402,10 @@ impl<'a> State<'a> {
402402
}
403403
hir::TyKind::Path(ref qpath) => self.print_qpath(qpath, false),
404404
hir::TyKind::TraitObject(bounds, lifetime, syntax) => {
405-
if syntax == ast::TraitObjectSyntax::Dyn {
406-
self.word_space("dyn");
405+
match syntax {
406+
ast::TraitObjectSyntax::Dyn => self.word_nbsp("dyn"),
407+
ast::TraitObjectSyntax::DynStar => self.word_nbsp("dyn*"),
408+
ast::TraitObjectSyntax::None => {}
407409
}
408410
let mut first = true;
409411
for bound in bounds {

compiler/rustc_middle/src/mir/syntax.rs

+5
Original file line numberDiff line numberDiff line change
@@ -821,6 +821,11 @@ pub enum TerminatorKind<'tcx> {
821821
/// continues at the `resume` basic block, with the second argument written to the `resume_arg`
822822
/// place. If the coroutine is dropped before then, the `drop` basic block is invoked.
823823
///
824+
/// Note that coroutines can be (unstably) cloned under certain conditions, which means that
825+
/// this terminator can **return multiple times**! MIR optimizations that reorder code into
826+
/// different basic blocks needs to be aware of that.
827+
/// See <https://github.com/rust-lang/rust/issues/95360>.
828+
///
824829
/// Not permitted in bodies that are not coroutine bodies, or after coroutine lowering.
825830
///
826831
/// **Needs clarification**: What about the evaluation order of the `resume_arg` and `value`?

library/core/src/primitive_docs.rs

+5-5
Original file line numberDiff line numberDiff line change
@@ -563,11 +563,11 @@ impl () {}
563563
/// Note that here the call to [`drop`] is for clarity - it indicates
564564
/// that we are done with the given value and it should be destroyed.
565565
///
566-
/// ## 3. Create it using `ptr::addr_of!`
566+
/// ## 3. Create it using `&raw`
567567
///
568-
/// Instead of coercing a reference to a raw pointer, you can use the macros
569-
/// [`ptr::addr_of!`] (for `*const T`) and [`ptr::addr_of_mut!`] (for `*mut T`).
570-
/// These macros allow you to create raw pointers to fields to which you cannot
568+
/// Instead of coercing a reference to a raw pointer, you can use the raw borrow
569+
/// operators `&raw const` (for `*const T`) and `&raw mut` (for `*mut T`).
570+
/// These operators allow you to create raw pointers to fields to which you cannot
571571
/// create a reference (without causing undefined behavior), such as an
572572
/// unaligned field. This might be necessary if packed structs or uninitialized
573573
/// memory is involved.
@@ -580,7 +580,7 @@ impl () {}
580580
/// unaligned: u32,
581581
/// }
582582
/// let s = S::default();
583-
/// let p = std::ptr::addr_of!(s.unaligned); // not allowed with coercion
583+
/// let p = &raw const s.unaligned; // not allowed with coercion
584584
/// ```
585585
///
586586
/// ## 4. Get it from C.

tests/ui-fulldeps/pprust-parenthesis-insertion.rs

-4
Original file line numberDiff line numberDiff line change
@@ -135,10 +135,6 @@ static EXPRS: &[&str] = &[
135135
"(0.).to_string()",
136136
"0. .. 1.",
137137
*/
138-
/*
139-
// FIXME: pretty-printer loses the dyn*. `i as Trait`
140-
"i as dyn* Trait",
141-
*/
142138
];
143139

144140
// Flatten the content of parenthesis nodes into their parent node. For example

tests/ui/coroutine/clone-impl-static.rs

+2
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
//@compile-flags: --diagnostic-width=300
22
// gate-test-coroutine_clone
33
// Verifies that static coroutines cannot be cloned/copied.
4+
// This is important: the cloned coroutine would reference state of the original
5+
// coroutine, leading to semantic nonsense.
46

57
#![feature(coroutines, coroutine_clone, stmt_expr_attributes)]
68

tests/ui/coroutine/clone-impl-static.stderr

+8-8
Original file line numberDiff line numberDiff line change
@@ -1,27 +1,27 @@
1-
error[E0277]: the trait bound `{static coroutine@$DIR/clone-impl-static.rs:9:5: 9:19}: Copy` is not satisfied
2-
--> $DIR/clone-impl-static.rs:12:16
1+
error[E0277]: the trait bound `{static coroutine@$DIR/clone-impl-static.rs:11:5: 11:19}: Copy` is not satisfied
2+
--> $DIR/clone-impl-static.rs:14:16
33
|
44
LL | check_copy(&gen);
5-
| ---------- ^^^^ the trait `Copy` is not implemented for `{static coroutine@$DIR/clone-impl-static.rs:9:5: 9:19}`
5+
| ---------- ^^^^ the trait `Copy` is not implemented for `{static coroutine@$DIR/clone-impl-static.rs:11:5: 11:19}`
66
| |
77
| required by a bound introduced by this call
88
|
99
note: required by a bound in `check_copy`
10-
--> $DIR/clone-impl-static.rs:18:18
10+
--> $DIR/clone-impl-static.rs:20:18
1111
|
1212
LL | fn check_copy<T: Copy>(_x: &T) {}
1313
| ^^^^ required by this bound in `check_copy`
1414

15-
error[E0277]: the trait bound `{static coroutine@$DIR/clone-impl-static.rs:9:5: 9:19}: Clone` is not satisfied
16-
--> $DIR/clone-impl-static.rs:14:17
15+
error[E0277]: the trait bound `{static coroutine@$DIR/clone-impl-static.rs:11:5: 11:19}: Clone` is not satisfied
16+
--> $DIR/clone-impl-static.rs:16:17
1717
|
1818
LL | check_clone(&gen);
19-
| ----------- ^^^^ the trait `Clone` is not implemented for `{static coroutine@$DIR/clone-impl-static.rs:9:5: 9:19}`
19+
| ----------- ^^^^ the trait `Clone` is not implemented for `{static coroutine@$DIR/clone-impl-static.rs:11:5: 11:19}`
2020
| |
2121
| required by a bound introduced by this call
2222
|
2323
note: required by a bound in `check_clone`
24-
--> $DIR/clone-impl-static.rs:19:19
24+
--> $DIR/clone-impl-static.rs:21:19
2525
|
2626
LL | fn check_clone<T: Clone>(_x: &T) {}
2727
| ^^^^^ required by this bound in `check_clone`

0 commit comments

Comments
 (0)