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
This commit is contained in:
commit
a2bcfae5c5
54 changed files with 367 additions and 198 deletions
|
@ -1204,8 +1204,10 @@ impl<'a> State<'a> {
|
|||
}
|
||||
ast::TyKind::Path(Some(qself), path) => self.print_qpath(path, qself, false),
|
||||
ast::TyKind::TraitObject(bounds, syntax) => {
|
||||
if *syntax == ast::TraitObjectSyntax::Dyn {
|
||||
self.word_nbsp("dyn");
|
||||
match syntax {
|
||||
ast::TraitObjectSyntax::Dyn => self.word_nbsp("dyn"),
|
||||
ast::TraitObjectSyntax::DynStar => self.word_nbsp("dyn*"),
|
||||
ast::TraitObjectSyntax::None => {}
|
||||
}
|
||||
self.print_type_bounds(bounds);
|
||||
}
|
||||
|
|
|
@ -249,9 +249,9 @@ builtin_macros_naked_functions_testing_attribute =
|
|||
.label = function marked with testing attribute here
|
||||
.naked_attribute = `#[naked]` is incompatible with testing attributes
|
||||
|
||||
builtin_macros_no_default_variant = no default declared
|
||||
.help = make a unit variant default by placing `#[default]` above it
|
||||
.suggestion = make `{$ident}` default
|
||||
builtin_macros_no_default_variant = `#[derive(Default)]` on enum with no `#[default]`
|
||||
.label = this enum needs a unit variant marked with `#[default]`
|
||||
.suggestion = make this unit variant default by placing `#[default]` on it
|
||||
|
||||
builtin_macros_non_abi = at least one abi must be provided as an argument to `clobber_abi`
|
||||
|
||||
|
|
|
@ -42,7 +42,9 @@ pub(crate) fn expand_deriving_default(
|
|||
StaticStruct(_, fields) => {
|
||||
default_struct_substructure(cx, trait_span, substr, fields)
|
||||
}
|
||||
StaticEnum(enum_def, _) => default_enum_substructure(cx, trait_span, enum_def),
|
||||
StaticEnum(enum_def, _) => {
|
||||
default_enum_substructure(cx, trait_span, enum_def, item.span())
|
||||
}
|
||||
_ => cx.dcx().span_bug(trait_span, "method in `derive(Default)`"),
|
||||
}
|
||||
})),
|
||||
|
@ -96,9 +98,10 @@ fn default_enum_substructure(
|
|||
cx: &ExtCtxt<'_>,
|
||||
trait_span: Span,
|
||||
enum_def: &EnumDef,
|
||||
item_span: Span,
|
||||
) -> BlockOrExpr {
|
||||
let expr = match try {
|
||||
let default_variant = extract_default_variant(cx, enum_def, trait_span)?;
|
||||
let default_variant = extract_default_variant(cx, enum_def, trait_span, item_span)?;
|
||||
validate_default_attribute(cx, default_variant)?;
|
||||
default_variant
|
||||
} {
|
||||
|
@ -146,6 +149,7 @@ fn extract_default_variant<'a>(
|
|||
cx: &ExtCtxt<'_>,
|
||||
enum_def: &'a EnumDef,
|
||||
trait_span: Span,
|
||||
item_span: Span,
|
||||
) -> Result<&'a rustc_ast::Variant, ErrorGuaranteed> {
|
||||
let default_variants: SmallVec<[_; 1]> = enum_def
|
||||
.variants
|
||||
|
@ -163,9 +167,10 @@ fn extract_default_variant<'a>(
|
|||
.filter(|variant| !attr::contains_name(&variant.attrs, sym::non_exhaustive));
|
||||
|
||||
let suggs = possible_defaults
|
||||
.map(|v| errors::NoDefaultVariantSugg { span: v.span, ident: v.ident })
|
||||
.map(|v| errors::NoDefaultVariantSugg { span: v.span.shrink_to_lo() })
|
||||
.collect();
|
||||
let guar = cx.dcx().emit_err(errors::NoDefaultVariant { span: trait_span, suggs });
|
||||
let guar =
|
||||
cx.dcx().emit_err(errors::NoDefaultVariant { span: trait_span, item_span, suggs });
|
||||
|
||||
return Err(guar);
|
||||
}
|
||||
|
|
|
@ -369,26 +369,21 @@ pub(crate) struct DerivePathArgsValue {
|
|||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(builtin_macros_no_default_variant)]
|
||||
#[help]
|
||||
#[diag(builtin_macros_no_default_variant, code = E0665)]
|
||||
pub(crate) struct NoDefaultVariant {
|
||||
#[primary_span]
|
||||
pub(crate) span: Span,
|
||||
#[label]
|
||||
pub(crate) item_span: Span,
|
||||
#[subdiagnostic]
|
||||
pub(crate) suggs: Vec<NoDefaultVariantSugg>,
|
||||
}
|
||||
|
||||
#[derive(Subdiagnostic)]
|
||||
#[suggestion(
|
||||
builtin_macros_suggestion,
|
||||
code = "#[default] {ident}",
|
||||
applicability = "maybe-incorrect",
|
||||
style = "tool-only"
|
||||
)]
|
||||
#[suggestion(builtin_macros_suggestion, code = "#[default] ", applicability = "maybe-incorrect")]
|
||||
pub(crate) struct NoDefaultVariantSugg {
|
||||
#[primary_span]
|
||||
pub(crate) span: Span,
|
||||
pub(crate) ident: Ident,
|
||||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
|
|
|
@ -1,10 +1,9 @@
|
|||
#### Note: this error code is no longer emitted by the compiler.
|
||||
|
||||
The `Default` trait was derived on an enum.
|
||||
The `Default` trait was derived on an enum without specifying the default
|
||||
variant.
|
||||
|
||||
Erroneous code example:
|
||||
|
||||
```compile_fail
|
||||
```compile_fail,E0665
|
||||
#[derive(Default)]
|
||||
enum Food {
|
||||
Sweet,
|
||||
|
@ -16,18 +15,30 @@ The `Default` cannot be derived on an enum for the simple reason that the
|
|||
compiler doesn't know which value to pick by default whereas it can for a
|
||||
struct as long as all its fields implement the `Default` trait as well.
|
||||
|
||||
If you still want to implement `Default` on your enum, you'll have to do it "by
|
||||
hand":
|
||||
For the case where the desired default variant has no payload, you can
|
||||
annotate it with `#[default]` to derive it:
|
||||
|
||||
```
|
||||
#[derive(Default)]
|
||||
enum Food {
|
||||
#[default]
|
||||
Sweet,
|
||||
Salty,
|
||||
}
|
||||
```
|
||||
|
||||
In the case where the default variant does have a payload, you will have to
|
||||
implement `Default` on your enum manually:
|
||||
|
||||
```
|
||||
enum Food {
|
||||
Sweet,
|
||||
Sweet(i32),
|
||||
Salty,
|
||||
}
|
||||
|
||||
impl Default for Food {
|
||||
fn default() -> Food {
|
||||
Food::Sweet
|
||||
Food::Sweet(1)
|
||||
}
|
||||
}
|
||||
```
|
||||
|
|
|
@ -673,37 +673,6 @@ fn visit_implementation_of_pointer_like(checker: &Checker<'_>) -> Result<(), Err
|
|||
let impl_span = tcx.def_span(checker.impl_def_id);
|
||||
let self_ty = tcx.impl_trait_ref(checker.impl_def_id).unwrap().instantiate_identity().self_ty();
|
||||
|
||||
// If an ADT is repr(transparent)...
|
||||
if let ty::Adt(def, args) = *self_ty.kind()
|
||||
&& def.repr().transparent()
|
||||
{
|
||||
// FIXME(compiler-errors): This should and could be deduplicated into a query.
|
||||
// Find the nontrivial field.
|
||||
let adt_typing_env = ty::TypingEnv::non_body_analysis(tcx, def.did());
|
||||
let nontrivial_field = def.all_fields().find(|field_def| {
|
||||
let field_ty = tcx.type_of(field_def.did).instantiate_identity();
|
||||
!tcx.layout_of(adt_typing_env.as_query_input(field_ty))
|
||||
.is_ok_and(|layout| layout.layout.is_1zst())
|
||||
});
|
||||
|
||||
if let Some(nontrivial_field) = nontrivial_field {
|
||||
// Check that the nontrivial field implements `PointerLike`.
|
||||
let nontrivial_field = nontrivial_field.ty(tcx, args);
|
||||
let (infcx, param_env) = tcx.infer_ctxt().build_with_typing_env(typing_env);
|
||||
let ocx = ObligationCtxt::new(&infcx);
|
||||
ocx.register_bound(
|
||||
ObligationCause::misc(impl_span, checker.impl_def_id),
|
||||
param_env,
|
||||
nontrivial_field,
|
||||
tcx.lang_items().pointer_like().unwrap(),
|
||||
);
|
||||
// FIXME(dyn-star): We should regionck this implementation.
|
||||
if ocx.select_all_or_error().is_empty() {
|
||||
return Ok(());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
let is_permitted_primitive = match *self_ty.kind() {
|
||||
ty::Adt(def, _) => def.is_box(),
|
||||
ty::Uint(..) | ty::Int(..) | ty::RawPtr(..) | ty::Ref(..) | ty::FnPtr(..) => true,
|
||||
|
@ -717,6 +686,74 @@ fn visit_implementation_of_pointer_like(checker: &Checker<'_>) -> Result<(), Err
|
|||
return Ok(());
|
||||
}
|
||||
|
||||
let why_disqualified = match *self_ty.kind() {
|
||||
// If an ADT is repr(transparent)
|
||||
ty::Adt(self_ty_def, args) => {
|
||||
if self_ty_def.repr().transparent() {
|
||||
// FIXME(compiler-errors): This should and could be deduplicated into a query.
|
||||
// Find the nontrivial field.
|
||||
let adt_typing_env = ty::TypingEnv::non_body_analysis(tcx, self_ty_def.did());
|
||||
let nontrivial_field = self_ty_def.all_fields().find(|field_def| {
|
||||
let field_ty = tcx.type_of(field_def.did).instantiate_identity();
|
||||
!tcx.layout_of(adt_typing_env.as_query_input(field_ty))
|
||||
.is_ok_and(|layout| layout.layout.is_1zst())
|
||||
});
|
||||
|
||||
if let Some(nontrivial_field) = nontrivial_field {
|
||||
// Check that the nontrivial field implements `PointerLike`.
|
||||
let nontrivial_field_ty = nontrivial_field.ty(tcx, args);
|
||||
let (infcx, param_env) = tcx.infer_ctxt().build_with_typing_env(typing_env);
|
||||
let ocx = ObligationCtxt::new(&infcx);
|
||||
ocx.register_bound(
|
||||
ObligationCause::misc(impl_span, checker.impl_def_id),
|
||||
param_env,
|
||||
nontrivial_field_ty,
|
||||
tcx.lang_items().pointer_like().unwrap(),
|
||||
);
|
||||
// FIXME(dyn-star): We should regionck this implementation.
|
||||
if ocx.select_all_or_error().is_empty() {
|
||||
return Ok(());
|
||||
} else {
|
||||
format!(
|
||||
"the field `{field_name}` of {descr} `{self_ty}` \
|
||||
does not implement `PointerLike`",
|
||||
field_name = nontrivial_field.name,
|
||||
descr = self_ty_def.descr()
|
||||
)
|
||||
}
|
||||
} else {
|
||||
format!(
|
||||
"the {descr} `{self_ty}` is `repr(transparent)`, \
|
||||
but does not have a non-trivial field (it is zero-sized)",
|
||||
descr = self_ty_def.descr()
|
||||
)
|
||||
}
|
||||
} else if self_ty_def.is_box() {
|
||||
// If we got here, then the `layout.is_pointer_like()` check failed
|
||||
// and this box is not a thin pointer.
|
||||
|
||||
String::from("boxes of dynamically-sized types are too large to be `PointerLike`")
|
||||
} else {
|
||||
format!(
|
||||
"the {descr} `{self_ty}` is not `repr(transparent)`",
|
||||
descr = self_ty_def.descr()
|
||||
)
|
||||
}
|
||||
}
|
||||
ty::Ref(..) => {
|
||||
// If we got here, then the `layout.is_pointer_like()` check failed
|
||||
// and this reference is not a thin pointer.
|
||||
String::from("references to dynamically-sized types are too large to be `PointerLike`")
|
||||
}
|
||||
ty::Dynamic(..) | ty::Foreign(..) => {
|
||||
String::from("types of dynamic or unknown size may not implement `PointerLike`")
|
||||
}
|
||||
_ => {
|
||||
// This is a white lie; it is true everywhere outside the standard library.
|
||||
format!("only user-defined sized types are eligible for `impl PointerLike`")
|
||||
}
|
||||
};
|
||||
|
||||
Err(tcx
|
||||
.dcx()
|
||||
.struct_span_err(
|
||||
|
@ -724,5 +761,6 @@ fn visit_implementation_of_pointer_like(checker: &Checker<'_>) -> Result<(), Err
|
|||
"implementation must be applied to type that has the same ABI as a pointer, \
|
||||
or is `repr(transparent)` and whose field is `PointerLike`",
|
||||
)
|
||||
.with_note(why_disqualified)
|
||||
.emit())
|
||||
}
|
||||
|
|
|
@ -402,8 +402,10 @@ impl<'a> State<'a> {
|
|||
}
|
||||
hir::TyKind::Path(ref qpath) => self.print_qpath(qpath, false),
|
||||
hir::TyKind::TraitObject(bounds, lifetime, syntax) => {
|
||||
if syntax == ast::TraitObjectSyntax::Dyn {
|
||||
self.word_space("dyn");
|
||||
match syntax {
|
||||
ast::TraitObjectSyntax::Dyn => self.word_nbsp("dyn"),
|
||||
ast::TraitObjectSyntax::DynStar => self.word_nbsp("dyn*"),
|
||||
ast::TraitObjectSyntax::None => {}
|
||||
}
|
||||
let mut first = true;
|
||||
for bound in bounds {
|
||||
|
|
|
@ -821,6 +821,11 @@ pub enum TerminatorKind<'tcx> {
|
|||
/// continues at the `resume` basic block, with the second argument written to the `resume_arg`
|
||||
/// place. If the coroutine is dropped before then, the `drop` basic block is invoked.
|
||||
///
|
||||
/// Note that coroutines can be (unstably) cloned under certain conditions, which means that
|
||||
/// this terminator can **return multiple times**! MIR optimizations that reorder code into
|
||||
/// different basic blocks needs to be aware of that.
|
||||
/// See <https://github.com/rust-lang/rust/issues/95360>.
|
||||
///
|
||||
/// Not permitted in bodies that are not coroutine bodies, or after coroutine lowering.
|
||||
///
|
||||
/// **Needs clarification**: What about the evaluation order of the `resume_arg` and `value`?
|
||||
|
|
|
@ -563,11 +563,11 @@ impl () {}
|
|||
/// Note that here the call to [`drop`] is for clarity - it indicates
|
||||
/// that we are done with the given value and it should be destroyed.
|
||||
///
|
||||
/// ## 3. Create it using `ptr::addr_of!`
|
||||
/// ## 3. Create it using `&raw`
|
||||
///
|
||||
/// Instead of coercing a reference to a raw pointer, you can use the macros
|
||||
/// [`ptr::addr_of!`] (for `*const T`) and [`ptr::addr_of_mut!`] (for `*mut T`).
|
||||
/// These macros allow you to create raw pointers to fields to which you cannot
|
||||
/// Instead of coercing a reference to a raw pointer, you can use the raw borrow
|
||||
/// operators `&raw const` (for `*const T`) and `&raw mut` (for `*mut T`).
|
||||
/// These operators allow you to create raw pointers to fields to which you cannot
|
||||
/// create a reference (without causing undefined behavior), such as an
|
||||
/// unaligned field. This might be necessary if packed structs or uninitialized
|
||||
/// memory is involved.
|
||||
|
@ -580,7 +580,7 @@ impl () {}
|
|||
/// unaligned: u32,
|
||||
/// }
|
||||
/// let s = S::default();
|
||||
/// let p = std::ptr::addr_of!(s.unaligned); // not allowed with coercion
|
||||
/// let p = &raw const s.unaligned; // not allowed with coercion
|
||||
/// ```
|
||||
///
|
||||
/// ## 4. Get it from C.
|
||||
|
|
|
@ -135,10 +135,6 @@ static EXPRS: &[&str] = &[
|
|||
"(0.).to_string()",
|
||||
"0. .. 1.",
|
||||
*/
|
||||
/*
|
||||
// FIXME: pretty-printer loses the dyn*. `i as Trait`
|
||||
"i as dyn* Trait",
|
||||
*/
|
||||
];
|
||||
|
||||
// Flatten the content of parenthesis nodes into their parent node. For example
|
||||
|
|
|
@ -1,6 +1,8 @@
|
|||
//@compile-flags: --diagnostic-width=300
|
||||
// gate-test-coroutine_clone
|
||||
// Verifies that static coroutines cannot be cloned/copied.
|
||||
// This is important: the cloned coroutine would reference state of the original
|
||||
// coroutine, leading to semantic nonsense.
|
||||
|
||||
#![feature(coroutines, coroutine_clone, stmt_expr_attributes)]
|
||||
|
||||
|
|
|
@ -1,27 +1,27 @@
|
|||
error[E0277]: the trait bound `{static coroutine@$DIR/clone-impl-static.rs:9:5: 9:19}: Copy` is not satisfied
|
||||
--> $DIR/clone-impl-static.rs:12:16
|
||||
error[E0277]: the trait bound `{static coroutine@$DIR/clone-impl-static.rs:11:5: 11:19}: Copy` is not satisfied
|
||||
--> $DIR/clone-impl-static.rs:14:16
|
||||
|
|
||||
LL | check_copy(&gen);
|
||||
| ---------- ^^^^ the trait `Copy` is not implemented for `{static coroutine@$DIR/clone-impl-static.rs:9:5: 9:19}`
|
||||
| ---------- ^^^^ the trait `Copy` is not implemented for `{static coroutine@$DIR/clone-impl-static.rs:11:5: 11:19}`
|
||||
| |
|
||||
| required by a bound introduced by this call
|
||||
|
|
||||
note: required by a bound in `check_copy`
|
||||
--> $DIR/clone-impl-static.rs:18:18
|
||||
--> $DIR/clone-impl-static.rs:20:18
|
||||
|
|
||||
LL | fn check_copy<T: Copy>(_x: &T) {}
|
||||
| ^^^^ required by this bound in `check_copy`
|
||||
|
||||
error[E0277]: the trait bound `{static coroutine@$DIR/clone-impl-static.rs:9:5: 9:19}: Clone` is not satisfied
|
||||
--> $DIR/clone-impl-static.rs:14:17
|
||||
error[E0277]: the trait bound `{static coroutine@$DIR/clone-impl-static.rs:11:5: 11:19}: Clone` is not satisfied
|
||||
--> $DIR/clone-impl-static.rs:16:17
|
||||
|
|
||||
LL | check_clone(&gen);
|
||||
| ----------- ^^^^ the trait `Clone` is not implemented for `{static coroutine@$DIR/clone-impl-static.rs:9:5: 9:19}`
|
||||
| ----------- ^^^^ the trait `Clone` is not implemented for `{static coroutine@$DIR/clone-impl-static.rs:11:5: 11:19}`
|
||||
| |
|
||||
| required by a bound introduced by this call
|
||||
|
|
||||
note: required by a bound in `check_clone`
|
||||
--> $DIR/clone-impl-static.rs:19:19
|
||||
--> $DIR/clone-impl-static.rs:21:19
|
||||
|
|
||||
LL | fn check_clone<T: Clone>(_x: &T) {}
|
||||
| ^^^^^ required by this bound in `check_clone`
|
||||
|
|
82
tests/ui/dyn-star/pointer-like-impl-rules.rs
Normal file
82
tests/ui/dyn-star/pointer-like-impl-rules.rs
Normal file
|
@ -0,0 +1,82 @@
|
|||
//@ check-fail
|
||||
|
||||
#![feature(extern_types)]
|
||||
#![feature(pointer_like_trait)]
|
||||
|
||||
use std::marker::PointerLike;
|
||||
|
||||
struct NotReprTransparent;
|
||||
impl PointerLike for NotReprTransparent {}
|
||||
//~^ ERROR: implementation must be applied to type that
|
||||
//~| NOTE: the struct `NotReprTransparent` is not `repr(transparent)`
|
||||
|
||||
#[repr(transparent)]
|
||||
struct FieldIsPl(usize);
|
||||
impl PointerLike for FieldIsPl {}
|
||||
|
||||
#[repr(transparent)]
|
||||
struct FieldIsPlAndHasOtherField(usize, ());
|
||||
impl PointerLike for FieldIsPlAndHasOtherField {}
|
||||
|
||||
#[repr(transparent)]
|
||||
struct FieldIsNotPl(u8);
|
||||
impl PointerLike for FieldIsNotPl {}
|
||||
//~^ ERROR: implementation must be applied to type that
|
||||
//~| NOTE: the field `0` of struct `FieldIsNotPl` does not implement `PointerLike`
|
||||
|
||||
#[repr(transparent)]
|
||||
struct GenericFieldIsNotPl<T>(T);
|
||||
impl<T> PointerLike for GenericFieldIsNotPl<T> {}
|
||||
//~^ ERROR: implementation must be applied to type that
|
||||
//~| NOTE: the field `0` of struct `GenericFieldIsNotPl<T>` does not implement `PointerLike`
|
||||
|
||||
#[repr(transparent)]
|
||||
struct GenericFieldIsPl<T>(T);
|
||||
impl<T: PointerLike> PointerLike for GenericFieldIsPl<T> {}
|
||||
|
||||
#[repr(transparent)]
|
||||
struct IsZeroSized(());
|
||||
impl PointerLike for IsZeroSized {}
|
||||
//~^ ERROR: implementation must be applied to type that
|
||||
//~| NOTE: the struct `IsZeroSized` is `repr(transparent)`, but does not have a non-trivial field
|
||||
|
||||
trait SomeTrait {}
|
||||
impl PointerLike for dyn SomeTrait {}
|
||||
//~^ ERROR: implementation must be applied to type that
|
||||
//~| NOTE: types of dynamic or unknown size
|
||||
|
||||
extern "C" {
|
||||
type ExternType;
|
||||
}
|
||||
impl PointerLike for ExternType {}
|
||||
//~^ ERROR: implementation must be applied to type that
|
||||
//~| NOTE: types of dynamic or unknown size
|
||||
|
||||
struct LocalSizedType(&'static str);
|
||||
struct LocalUnsizedType(str);
|
||||
|
||||
// This is not a special error but a normal coherence error,
|
||||
// which should still happen.
|
||||
impl PointerLike for &LocalSizedType {}
|
||||
//~^ ERROR: conflicting implementations of trait `PointerLike`
|
||||
//~| NOTE: conflicting implementation in crate `core`
|
||||
|
||||
impl PointerLike for &LocalUnsizedType {}
|
||||
//~^ ERROR: implementation must be applied to type that
|
||||
//~| NOTE: references to dynamically-sized types are too large to be `PointerLike`
|
||||
|
||||
impl PointerLike for Box<LocalSizedType> {}
|
||||
//~^ ERROR: conflicting implementations of trait `PointerLike`
|
||||
//~| NOTE: conflicting implementation in crate `alloc`
|
||||
|
||||
impl PointerLike for Box<LocalUnsizedType> {}
|
||||
//~^ ERROR: implementation must be applied to type that
|
||||
//~| NOTE: boxes of dynamically-sized types are too large to be `PointerLike`
|
||||
|
||||
fn expects_pointer_like(x: impl PointerLike) {}
|
||||
|
||||
fn main() {
|
||||
expects_pointer_like(FieldIsPl(1usize));
|
||||
expects_pointer_like(FieldIsPlAndHasOtherField(1usize, ()));
|
||||
expects_pointer_like(GenericFieldIsPl(1usize));
|
||||
}
|
85
tests/ui/dyn-star/pointer-like-impl-rules.stderr
Normal file
85
tests/ui/dyn-star/pointer-like-impl-rules.stderr
Normal file
|
@ -0,0 +1,85 @@
|
|||
error[E0119]: conflicting implementations of trait `PointerLike` for type `&LocalSizedType`
|
||||
--> $DIR/pointer-like-impl-rules.rs:60:1
|
||||
|
|
||||
LL | impl PointerLike for &LocalSizedType {}
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
= note: conflicting implementation in crate `core`:
|
||||
- impl<T> PointerLike for &T;
|
||||
|
||||
error[E0119]: conflicting implementations of trait `PointerLike` for type `Box<LocalSizedType>`
|
||||
--> $DIR/pointer-like-impl-rules.rs:68:1
|
||||
|
|
||||
LL | impl PointerLike for Box<LocalSizedType> {}
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
= note: conflicting implementation in crate `alloc`:
|
||||
- impl<T> PointerLike for Box<T>;
|
||||
|
||||
error: implementation must be applied to type that has the same ABI as a pointer, or is `repr(transparent)` and whose field is `PointerLike`
|
||||
--> $DIR/pointer-like-impl-rules.rs:9:1
|
||||
|
|
||||
LL | impl PointerLike for NotReprTransparent {}
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
= note: the struct `NotReprTransparent` is not `repr(transparent)`
|
||||
|
||||
error: implementation must be applied to type that has the same ABI as a pointer, or is `repr(transparent)` and whose field is `PointerLike`
|
||||
--> $DIR/pointer-like-impl-rules.rs:23:1
|
||||
|
|
||||
LL | impl PointerLike for FieldIsNotPl {}
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
= note: the field `0` of struct `FieldIsNotPl` does not implement `PointerLike`
|
||||
|
||||
error: implementation must be applied to type that has the same ABI as a pointer, or is `repr(transparent)` and whose field is `PointerLike`
|
||||
--> $DIR/pointer-like-impl-rules.rs:29:1
|
||||
|
|
||||
LL | impl<T> PointerLike for GenericFieldIsNotPl<T> {}
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
= note: the field `0` of struct `GenericFieldIsNotPl<T>` does not implement `PointerLike`
|
||||
|
||||
error: implementation must be applied to type that has the same ABI as a pointer, or is `repr(transparent)` and whose field is `PointerLike`
|
||||
--> $DIR/pointer-like-impl-rules.rs:39:1
|
||||
|
|
||||
LL | impl PointerLike for IsZeroSized {}
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
= note: the struct `IsZeroSized` is `repr(transparent)`, but does not have a non-trivial field (it is zero-sized)
|
||||
|
||||
error: implementation must be applied to type that has the same ABI as a pointer, or is `repr(transparent)` and whose field is `PointerLike`
|
||||
--> $DIR/pointer-like-impl-rules.rs:44:1
|
||||
|
|
||||
LL | impl PointerLike for dyn SomeTrait {}
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
= note: types of dynamic or unknown size may not implement `PointerLike`
|
||||
|
||||
error: implementation must be applied to type that has the same ABI as a pointer, or is `repr(transparent)` and whose field is `PointerLike`
|
||||
--> $DIR/pointer-like-impl-rules.rs:51:1
|
||||
|
|
||||
LL | impl PointerLike for ExternType {}
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
= note: types of dynamic or unknown size may not implement `PointerLike`
|
||||
|
||||
error: implementation must be applied to type that has the same ABI as a pointer, or is `repr(transparent)` and whose field is `PointerLike`
|
||||
--> $DIR/pointer-like-impl-rules.rs:64:1
|
||||
|
|
||||
LL | impl PointerLike for &LocalUnsizedType {}
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
= note: references to dynamically-sized types are too large to be `PointerLike`
|
||||
|
||||
error: implementation must be applied to type that has the same ABI as a pointer, or is `repr(transparent)` and whose field is `PointerLike`
|
||||
--> $DIR/pointer-like-impl-rules.rs:72:1
|
||||
|
|
||||
LL | impl PointerLike for Box<LocalUnsizedType> {}
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
= note: boxes of dynamically-sized types are too large to be `PointerLike`
|
||||
|
||||
error: aborting due to 10 previous errors
|
||||
|
||||
For more information about this error, try `rustc --explain E0119`.
|
|
@ -39,12 +39,18 @@ enum AttrOnInnerExpression {
|
|||
Baz,
|
||||
}
|
||||
|
||||
#[derive(Default)] //~ ERROR no default declared
|
||||
#[derive(Default)] //~ ERROR `#[derive(Default)]` on enum with no `#[default]`
|
||||
enum NoDeclaredDefault {
|
||||
Foo,
|
||||
Bar,
|
||||
}
|
||||
|
||||
#[derive(Default)] //~ ERROR `#[derive(Default)]` on enum with no `#[default]`
|
||||
enum NoDeclaredDefaultWithoutUnitVariant {
|
||||
Foo(i32),
|
||||
Bar(i32),
|
||||
}
|
||||
|
||||
#[derive(Default)] //~ ERROR multiple declared defaults
|
||||
enum MultipleDefaults {
|
||||
#[default]
|
||||
|
|
|
@ -46,17 +46,42 @@ LL | Bar([u8; #[default] 1]),
|
|||
|
|
||||
= help: consider a manual implementation of `Default`
|
||||
|
||||
error: no default declared
|
||||
error[E0665]: `#[derive(Default)]` on enum with no `#[default]`
|
||||
--> $DIR/macros-nonfatal-errors.rs:42:10
|
||||
|
|
||||
LL | #[derive(Default)]
|
||||
| ^^^^^^^
|
||||
LL | #[derive(Default)]
|
||||
| ^^^^^^^
|
||||
LL | / enum NoDeclaredDefault {
|
||||
LL | | Foo,
|
||||
LL | | Bar,
|
||||
LL | | }
|
||||
| |_- this enum needs a unit variant marked with `#[default]`
|
||||
|
|
||||
= note: this error originates in the derive macro `Default` (in Nightly builds, run with -Z macro-backtrace for more info)
|
||||
help: make this unit variant default by placing `#[default]` on it
|
||||
|
|
||||
LL | #[default] Foo,
|
||||
| ++++++++++
|
||||
help: make this unit variant default by placing `#[default]` on it
|
||||
|
|
||||
LL | #[default] Bar,
|
||||
| ++++++++++
|
||||
|
||||
error[E0665]: `#[derive(Default)]` on enum with no `#[default]`
|
||||
--> $DIR/macros-nonfatal-errors.rs:48:10
|
||||
|
|
||||
LL | #[derive(Default)]
|
||||
| ^^^^^^^
|
||||
LL | / enum NoDeclaredDefaultWithoutUnitVariant {
|
||||
LL | | Foo(i32),
|
||||
LL | | Bar(i32),
|
||||
LL | | }
|
||||
| |_- this enum needs a unit variant marked with `#[default]`
|
||||
|
|
||||
= help: make a unit variant default by placing `#[default]` above it
|
||||
= note: this error originates in the derive macro `Default` (in Nightly builds, run with -Z macro-backtrace for more info)
|
||||
|
||||
error: multiple declared defaults
|
||||
--> $DIR/macros-nonfatal-errors.rs:48:10
|
||||
--> $DIR/macros-nonfatal-errors.rs:54:10
|
||||
|
|
||||
LL | #[derive(Default)]
|
||||
| ^^^^^^^
|
||||
|
@ -74,7 +99,7 @@ LL | Baz,
|
|||
= note: this error originates in the derive macro `Default` (in Nightly builds, run with -Z macro-backtrace for more info)
|
||||
|
||||
error: `#[default]` attribute does not accept a value
|
||||
--> $DIR/macros-nonfatal-errors.rs:60:5
|
||||
--> $DIR/macros-nonfatal-errors.rs:66:5
|
||||
|
|
||||
LL | #[default = 1]
|
||||
| ^^^^^^^^^^^^^^
|
||||
|
@ -82,7 +107,7 @@ LL | #[default = 1]
|
|||
= help: try using `#[default]`
|
||||
|
||||
error: multiple `#[default]` attributes
|
||||
--> $DIR/macros-nonfatal-errors.rs:68:5
|
||||
--> $DIR/macros-nonfatal-errors.rs:74:5
|
||||
|
|
||||
LL | #[default]
|
||||
| ---------- `#[default]` used here
|
||||
|
@ -93,13 +118,13 @@ LL | Foo,
|
|||
|
|
||||
= note: only one `#[default]` attribute is needed
|
||||
help: try removing this
|
||||
--> $DIR/macros-nonfatal-errors.rs:67:5
|
||||
--> $DIR/macros-nonfatal-errors.rs:73:5
|
||||
|
|
||||
LL | #[default]
|
||||
| ^^^^^^^^^^
|
||||
|
||||
error: multiple `#[default]` attributes
|
||||
--> $DIR/macros-nonfatal-errors.rs:78:5
|
||||
--> $DIR/macros-nonfatal-errors.rs:84:5
|
||||
|
|
||||
LL | #[default]
|
||||
| ---------- `#[default]` used here
|
||||
|
@ -111,7 +136,7 @@ LL | Foo,
|
|||
|
|
||||
= note: only one `#[default]` attribute is needed
|
||||
help: try removing these
|
||||
--> $DIR/macros-nonfatal-errors.rs:75:5
|
||||
--> $DIR/macros-nonfatal-errors.rs:81:5
|
||||
|
|
||||
LL | #[default]
|
||||
| ^^^^^^^^^^
|
||||
|
@ -121,7 +146,7 @@ LL | #[default]
|
|||
| ^^^^^^^^^^
|
||||
|
||||
error: the `#[default]` attribute may only be used on unit enum variants
|
||||
--> $DIR/macros-nonfatal-errors.rs:85:5
|
||||
--> $DIR/macros-nonfatal-errors.rs:91:5
|
||||
|
|
||||
LL | Foo {},
|
||||
| ^^^
|
||||
|
@ -129,7 +154,7 @@ LL | Foo {},
|
|||
= help: consider a manual implementation of `Default`
|
||||
|
||||
error: default variant must be exhaustive
|
||||
--> $DIR/macros-nonfatal-errors.rs:93:5
|
||||
--> $DIR/macros-nonfatal-errors.rs:99:5
|
||||
|
|
||||
LL | #[non_exhaustive]
|
||||
| ----------------- declared `#[non_exhaustive]` here
|
||||
|
@ -139,37 +164,37 @@ LL | Foo,
|
|||
= help: consider a manual implementation of `Default`
|
||||
|
||||
error: asm template must be a string literal
|
||||
--> $DIR/macros-nonfatal-errors.rs:98:10
|
||||
--> $DIR/macros-nonfatal-errors.rs:104:10
|
||||
|
|
||||
LL | asm!(invalid);
|
||||
| ^^^^^^^
|
||||
|
||||
error: `concat_idents!()` requires ident args
|
||||
--> $DIR/macros-nonfatal-errors.rs:101:5
|
||||
--> $DIR/macros-nonfatal-errors.rs:107:5
|
||||
|
|
||||
LL | concat_idents!("not", "idents");
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
error: argument must be a string literal
|
||||
--> $DIR/macros-nonfatal-errors.rs:103:17
|
||||
--> $DIR/macros-nonfatal-errors.rs:109:17
|
||||
|
|
||||
LL | option_env!(invalid);
|
||||
| ^^^^^^^
|
||||
|
||||
error: expected string literal
|
||||
--> $DIR/macros-nonfatal-errors.rs:104:10
|
||||
--> $DIR/macros-nonfatal-errors.rs:110:10
|
||||
|
|
||||
LL | env!(invalid);
|
||||
| ^^^^^^^
|
||||
|
||||
error: `env!()` takes 1 or 2 arguments
|
||||
--> $DIR/macros-nonfatal-errors.rs:105:5
|
||||
--> $DIR/macros-nonfatal-errors.rs:111:5
|
||||
|
|
||||
LL | env!(foo, abr, baz);
|
||||
| ^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
error: environment variable `RUST_HOPEFULLY_THIS_DOESNT_EXIST` not defined at compile time
|
||||
--> $DIR/macros-nonfatal-errors.rs:106:5
|
||||
--> $DIR/macros-nonfatal-errors.rs:112:5
|
||||
|
|
||||
LL | env!("RUST_HOPEFULLY_THIS_DOESNT_EXIST");
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
@ -178,7 +203,7 @@ LL | env!("RUST_HOPEFULLY_THIS_DOESNT_EXIST");
|
|||
= note: this error originates in the macro `env` (in Nightly builds, run with -Z macro-backtrace for more info)
|
||||
|
||||
error: format argument must be a string literal
|
||||
--> $DIR/macros-nonfatal-errors.rs:108:13
|
||||
--> $DIR/macros-nonfatal-errors.rs:114:13
|
||||
|
|
||||
LL | format!(invalid);
|
||||
| ^^^^^^^
|
||||
|
@ -189,19 +214,19 @@ LL | format!("{}", invalid);
|
|||
| +++++
|
||||
|
||||
error: argument must be a string literal
|
||||
--> $DIR/macros-nonfatal-errors.rs:110:14
|
||||
--> $DIR/macros-nonfatal-errors.rs:116:14
|
||||
|
|
||||
LL | include!(invalid);
|
||||
| ^^^^^^^
|
||||
|
||||
error: argument must be a string literal
|
||||
--> $DIR/macros-nonfatal-errors.rs:112:18
|
||||
--> $DIR/macros-nonfatal-errors.rs:118:18
|
||||
|
|
||||
LL | include_str!(invalid);
|
||||
| ^^^^^^^
|
||||
|
||||
error: couldn't read `$DIR/i'd be quite surprised if a file with this name existed`: $FILE_NOT_FOUND_MSG
|
||||
--> $DIR/macros-nonfatal-errors.rs:113:5
|
||||
--> $DIR/macros-nonfatal-errors.rs:119:5
|
||||
|
|
||||
LL | include_str!("i'd be quite surprised if a file with this name existed");
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
@ -209,13 +234,13 @@ LL | include_str!("i'd be quite surprised if a file with this name existed")
|
|||
= note: this error originates in the macro `include_str` (in Nightly builds, run with -Z macro-backtrace for more info)
|
||||
|
||||
error: argument must be a string literal
|
||||
--> $DIR/macros-nonfatal-errors.rs:114:20
|
||||
--> $DIR/macros-nonfatal-errors.rs:120:20
|
||||
|
|
||||
LL | include_bytes!(invalid);
|
||||
| ^^^^^^^
|
||||
|
||||
error: couldn't read `$DIR/i'd be quite surprised if a file with this name existed`: $FILE_NOT_FOUND_MSG
|
||||
--> $DIR/macros-nonfatal-errors.rs:115:5
|
||||
--> $DIR/macros-nonfatal-errors.rs:121:5
|
||||
|
|
||||
LL | include_bytes!("i'd be quite surprised if a file with this name existed");
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
@ -223,13 +248,13 @@ LL | include_bytes!("i'd be quite surprised if a file with this name existed
|
|||
= note: this error originates in the macro `include_bytes` (in Nightly builds, run with -Z macro-backtrace for more info)
|
||||
|
||||
error: trace_macros! accepts only `true` or `false`
|
||||
--> $DIR/macros-nonfatal-errors.rs:117:5
|
||||
--> $DIR/macros-nonfatal-errors.rs:123:5
|
||||
|
|
||||
LL | trace_macros!(invalid);
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
error: default variant must be exhaustive
|
||||
--> $DIR/macros-nonfatal-errors.rs:127:9
|
||||
--> $DIR/macros-nonfatal-errors.rs:133:9
|
||||
|
|
||||
LL | #[non_exhaustive]
|
||||
| ----------------- declared `#[non_exhaustive]` here
|
||||
|
@ -239,10 +264,11 @@ LL | Foo,
|
|||
= help: consider a manual implementation of `Default`
|
||||
|
||||
error: cannot find macro `llvm_asm` in this scope
|
||||
--> $DIR/macros-nonfatal-errors.rs:99:5
|
||||
--> $DIR/macros-nonfatal-errors.rs:105:5
|
||||
|
|
||||
LL | llvm_asm!(invalid);
|
||||
| ^^^^^^^^
|
||||
|
||||
error: aborting due to 28 previous errors
|
||||
error: aborting due to 29 previous errors
|
||||
|
||||
For more information about this error, try `rustc --explain E0665`.
|
||||
|
|
|
@ -58,14 +58,14 @@ help: consider adding an explicit lifetime bound
|
|||
LL | executor: impl FnOnce(T) -> (dyn Future<Output = ()>) + 'static,
|
||||
| + +++++++++++
|
||||
|
||||
error[E0310]: the parameter type `impl FnOnce(T) -> Future<Output = ()>` may not live long enough
|
||||
error[E0310]: the parameter type `impl FnOnce(T) -> dyn* Future<Output = ()>` may not live long enough
|
||||
--> $DIR/wrap-dyn-in-suggestion-issue-120223.rs:14:5
|
||||
|
|
||||
LL | Box::new(executor)
|
||||
| ^^^^^^^^^^^^^^^^^^
|
||||
| |
|
||||
| the parameter type `impl FnOnce(T) -> Future<Output = ()>` must be valid for the static lifetime...
|
||||
| ...so that the type `impl FnOnce(T) -> Future<Output = ()>` will meet its required lifetime bounds
|
||||
| the parameter type `impl FnOnce(T) -> dyn* Future<Output = ()>` must be valid for the static lifetime...
|
||||
| ...so that the type `impl FnOnce(T) -> dyn* Future<Output = ()>` will meet its required lifetime bounds
|
||||
|
|
||||
help: consider adding an explicit lifetime bound
|
||||
|
|
||||
|
|
|
@ -1,13 +0,0 @@
|
|||
//@ compile-flags: -Znext-solver
|
||||
#![feature(const_trait_impl)]
|
||||
|
||||
pub const fn foo() {}
|
||||
|
||||
#[const_trait]
|
||||
pub trait Bar {
|
||||
fn bar();
|
||||
}
|
||||
|
||||
impl Bar for () {
|
||||
fn bar() {}
|
||||
}
|
|
@ -1,18 +0,0 @@
|
|||
//@ aux-build: cross-crate.rs
|
||||
extern crate cross_crate;
|
||||
|
||||
use cross_crate::{Bar, foo};
|
||||
|
||||
fn main() {
|
||||
foo::<true>();
|
||||
//~^ ERROR: function takes 0 generic arguments but 1 generic argument was supplied
|
||||
<() as Bar<true>>::bar();
|
||||
//~^ ERROR: trait takes 0 generic arguments but 1 generic argument was supplied
|
||||
}
|
||||
|
||||
const FOO: () = {
|
||||
foo::<false>();
|
||||
//~^ ERROR: function takes 0 generic arguments but 1 generic argument was supplied
|
||||
<() as Bar<false>>::bar();
|
||||
//~^ ERROR: trait takes 0 generic arguments but 1 generic argument was supplied
|
||||
};
|
|
@ -1,59 +0,0 @@
|
|||
error[E0107]: function takes 0 generic arguments but 1 generic argument was supplied
|
||||
--> $DIR/no-explicit-const-params-cross-crate.rs:14:5
|
||||
|
|
||||
LL | foo::<false>();
|
||||
| ^^^--------- help: remove the unnecessary generics
|
||||
| |
|
||||
| expected 0 generic arguments
|
||||
|
|
||||
note: function defined here, with 0 generic parameters
|
||||
--> $DIR/auxiliary/cross-crate.rs:4:14
|
||||
|
|
||||
LL | pub const fn foo() {}
|
||||
| ^^^
|
||||
|
||||
error[E0107]: trait takes 0 generic arguments but 1 generic argument was supplied
|
||||
--> $DIR/no-explicit-const-params-cross-crate.rs:16:12
|
||||
|
|
||||
LL | <() as Bar<false>>::bar();
|
||||
| ^^^------- help: remove the unnecessary generics
|
||||
| |
|
||||
| expected 0 generic arguments
|
||||
|
|
||||
note: trait defined here, with 0 generic parameters
|
||||
--> $DIR/auxiliary/cross-crate.rs:7:11
|
||||
|
|
||||
LL | pub trait Bar {
|
||||
| ^^^
|
||||
|
||||
error[E0107]: function takes 0 generic arguments but 1 generic argument was supplied
|
||||
--> $DIR/no-explicit-const-params-cross-crate.rs:7:5
|
||||
|
|
||||
LL | foo::<true>();
|
||||
| ^^^-------- help: remove the unnecessary generics
|
||||
| |
|
||||
| expected 0 generic arguments
|
||||
|
|
||||
note: function defined here, with 0 generic parameters
|
||||
--> $DIR/auxiliary/cross-crate.rs:4:14
|
||||
|
|
||||
LL | pub const fn foo() {}
|
||||
| ^^^
|
||||
|
||||
error[E0107]: trait takes 0 generic arguments but 1 generic argument was supplied
|
||||
--> $DIR/no-explicit-const-params-cross-crate.rs:9:12
|
||||
|
|
||||
LL | <() as Bar<true>>::bar();
|
||||
| ^^^------ help: remove the unnecessary generics
|
||||
| |
|
||||
| expected 0 generic arguments
|
||||
|
|
||||
note: trait defined here, with 0 generic parameters
|
||||
--> $DIR/auxiliary/cross-crate.rs:7:11
|
||||
|
|
||||
LL | pub trait Bar {
|
||||
| ^^^
|
||||
|
||||
error: aborting due to 4 previous errors
|
||||
|
||||
For more information about this error, try `rustc --explain E0107`.
|
|
@ -9,6 +9,7 @@
|
|||
#![feature(const_trait_impl)]
|
||||
#![feature(decl_macro)]
|
||||
#![feature(deref_patterns)]
|
||||
#![feature(dyn_star)]
|
||||
#![feature(explicit_tail_calls)]
|
||||
#![feature(gen_blocks)]
|
||||
#![feature(let_chains)]
|
||||
|
@ -800,6 +801,7 @@ mod types {
|
|||
let _: dyn Send + 'static;
|
||||
let _: dyn 'static + Send;
|
||||
let _: dyn for<'a> Send;
|
||||
let _: dyn* Send;
|
||||
}
|
||||
|
||||
/// TyKind::ImplTrait
|
||||
|
|
|
@ -10,6 +10,7 @@
|
|||
#![feature(const_trait_impl)]
|
||||
#![feature(decl_macro)]
|
||||
#![feature(deref_patterns)]
|
||||
#![feature(dyn_star)]
|
||||
#![feature(explicit_tail_calls)]
|
||||
#![feature(gen_blocks)]
|
||||
#![feature(let_chains)]
|
||||
|
@ -647,6 +648,7 @@ mod types {
|
|||
let _: dyn Send + 'static;
|
||||
let _: dyn 'static + Send;
|
||||
let _: dyn for<'a> Send;
|
||||
let _: dyn* Send;
|
||||
}
|
||||
/// TyKind::ImplTrait
|
||||
const fn ty_impl_trait() {
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue