Auto merge of #118200 - matthiaskrgr:rollup-neka6xo, r=matthiaskrgr
Rollup of 4 pull requests Successful merges: - #118131 (improve tool-only help for multiple `#[default]` variants) - #118146 (Rework supertrait lint once again) - #118167 (make the 'abi_unadjusted' feature internal) - #118169 (print query map for deadlock when using parallel front end) r? `@ghost` `@rustbot` modify labels: rollup
This commit is contained in:
commit
fc13ca6d70
@ -127,18 +127,17 @@ fn extract_default_variant<'a>(
|
||||
[first, rest @ ..] => {
|
||||
let suggs = default_variants
|
||||
.iter()
|
||||
.map(|variant| {
|
||||
let spans = default_variants
|
||||
.filter_map(|variant| {
|
||||
let keep = attr::find_by_name(&variant.attrs, kw::Default)?.span;
|
||||
let spans: Vec<Span> = default_variants
|
||||
.iter()
|
||||
.filter_map(|v| {
|
||||
if v.span == variant.span {
|
||||
None
|
||||
} else {
|
||||
Some(attr::find_by_name(&v.attrs, kw::Default)?.span)
|
||||
}
|
||||
.flat_map(|v| {
|
||||
attr::filter_by_name(&v.attrs, kw::Default)
|
||||
.filter_map(|attr| (attr.span != keep).then_some(attr.span))
|
||||
})
|
||||
.collect();
|
||||
errors::MultipleDefaultsSugg { spans, ident: variant.ident }
|
||||
(!spans.is_empty())
|
||||
.then_some(errors::MultipleDefaultsSugg { spans, ident: variant.ident })
|
||||
})
|
||||
.collect();
|
||||
cx.emit_err(errors::MultipleDefaults {
|
||||
|
@ -160,7 +160,7 @@ declare_features! (
|
||||
// no-tracking-issue-start
|
||||
|
||||
/// Allows using the `unadjusted` ABI; perma-unstable.
|
||||
(unstable, abi_unadjusted, "1.16.0", None, None),
|
||||
(internal, abi_unadjusted, "1.16.0", None, None),
|
||||
/// Allows using the `vectorcall` ABI.
|
||||
(unstable, abi_vectorcall, "1.7.0", None, None),
|
||||
/// Allows using `#![needs_allocator]`, an implementation detail of `#[global_allocator]`.
|
||||
|
@ -491,8 +491,9 @@ lint_requested_level = requested on the command line with `{$level} {$lint_name}
|
||||
lint_span_use_eq_ctxt = use `.eq_ctxt()` instead of `.ctxt() == .ctxt()`
|
||||
|
||||
lint_supertrait_as_deref_target = this `Deref` implementation is covered by an implicit supertrait coercion
|
||||
.label = `{$self_ty}` implements `Deref<Target = dyn {$target_principal}>` which conflicts with supertrait `{$supertrait_principal}`
|
||||
.label2 = target type is a supertrait of `{$self_ty}`
|
||||
.help = consider removing this implementation or replacing it with a method instead
|
||||
.label = target type is a supertrait of `{$t}`
|
||||
|
||||
lint_suspicious_double_ref_clone =
|
||||
using `.clone()` on a double reference, which returns `{$ty}` instead of cloning the inner type
|
||||
|
@ -53,35 +53,43 @@ impl<'tcx> LateLintPass<'tcx> for DerefIntoDynSupertrait {
|
||||
let tcx = cx.tcx;
|
||||
// `Deref` is being implemented for `t`
|
||||
if let hir::ItemKind::Impl(impl_) = item.kind
|
||||
// the trait is a `Deref` implementation
|
||||
&& let Some(trait_) = &impl_.of_trait
|
||||
&& let t = tcx.type_of(item.owner_id).instantiate_identity()
|
||||
&& let opt_did @ Some(did) = trait_.trait_def_id()
|
||||
&& opt_did == tcx.lang_items().deref_trait()
|
||||
// `t` is `dyn t_principal`
|
||||
&& let ty::Dynamic(data, _, ty::Dyn) = t.kind()
|
||||
&& let Some(t_principal) = data.principal()
|
||||
&& let Some(did) = trait_.trait_def_id()
|
||||
&& Some(did) == tcx.lang_items().deref_trait()
|
||||
// the self type is `dyn t_principal`
|
||||
&& let self_ty = tcx.type_of(item.owner_id).instantiate_identity()
|
||||
&& let ty::Dynamic(data, _, ty::Dyn) = self_ty.kind()
|
||||
&& let Some(self_principal) = data.principal()
|
||||
// `<T as Deref>::Target` is `dyn target_principal`
|
||||
&& let Some(target) = cx.get_associated_type(t, did, "Target")
|
||||
&& let Some(target) = cx.get_associated_type(self_ty, did, "Target")
|
||||
&& let ty::Dynamic(data, _, ty::Dyn) = target.kind()
|
||||
&& let Some(target_principal) = data.principal()
|
||||
// `target_principal` is a supertrait of `t_principal`
|
||||
&& supertraits(tcx, t_principal.with_self_ty(tcx, tcx.types.trait_object_dummy_self))
|
||||
.any(|sup| {
|
||||
tcx.erase_regions(
|
||||
sup.map_bound(|x| ty::ExistentialTraitRef::erase_self_ty(tcx, x)),
|
||||
) == tcx.erase_regions(target_principal)
|
||||
})
|
||||
&& let Some(supertrait_principal) = supertraits(tcx, self_principal.with_self_ty(tcx, self_ty))
|
||||
.find(|supertrait| supertrait.def_id() == target_principal.def_id())
|
||||
{
|
||||
let t = tcx.erase_regions(t);
|
||||
let label = impl_
|
||||
// erase regions in self type for better diagnostic presentation
|
||||
let (self_ty, target_principal, supertrait_principal) =
|
||||
tcx.erase_regions((self_ty, target_principal, supertrait_principal));
|
||||
let label2 = impl_
|
||||
.items
|
||||
.iter()
|
||||
.find_map(|i| (i.ident.name == sym::Target).then_some(i.span))
|
||||
.map(|label| SupertraitAsDerefTargetLabel { label });
|
||||
let span = tcx.def_span(item.owner_id.def_id);
|
||||
cx.emit_spanned_lint(
|
||||
DEREF_INTO_DYN_SUPERTRAIT,
|
||||
tcx.def_span(item.owner_id.def_id),
|
||||
SupertraitAsDerefTarget { t, label },
|
||||
span,
|
||||
SupertraitAsDerefTarget {
|
||||
self_ty,
|
||||
supertrait_principal: supertrait_principal.map_bound(|trait_ref| {
|
||||
ty::ExistentialTraitRef::erase_self_ty(tcx, trait_ref)
|
||||
}),
|
||||
target_principal,
|
||||
label: span,
|
||||
label2,
|
||||
},
|
||||
);
|
||||
}
|
||||
}
|
||||
|
@ -10,7 +10,9 @@ use rustc_errors::{
|
||||
};
|
||||
use rustc_hir::def_id::DefId;
|
||||
use rustc_macros::{LintDiagnostic, Subdiagnostic};
|
||||
use rustc_middle::ty::{inhabitedness::InhabitedPredicate, Clause, Ty, TyCtxt};
|
||||
use rustc_middle::ty::{
|
||||
inhabitedness::InhabitedPredicate, Clause, PolyExistentialTraitRef, Ty, TyCtxt,
|
||||
};
|
||||
use rustc_session::parse::ParseSess;
|
||||
use rustc_span::{edition::Edition, sym, symbol::Ident, Span, Symbol};
|
||||
|
||||
@ -556,13 +558,17 @@ pub enum BuiltinSpecialModuleNameUsed {
|
||||
#[diag(lint_supertrait_as_deref_target)]
|
||||
#[help]
|
||||
pub struct SupertraitAsDerefTarget<'a> {
|
||||
pub t: Ty<'a>,
|
||||
pub self_ty: Ty<'a>,
|
||||
pub supertrait_principal: PolyExistentialTraitRef<'a>,
|
||||
pub target_principal: PolyExistentialTraitRef<'a>,
|
||||
#[label]
|
||||
pub label: Span,
|
||||
#[subdiagnostic]
|
||||
pub label: Option<SupertraitAsDerefTargetLabel>,
|
||||
pub label2: Option<SupertraitAsDerefTargetLabel>,
|
||||
}
|
||||
|
||||
#[derive(Subdiagnostic)]
|
||||
#[label(lint_label)]
|
||||
#[label(lint_label2)]
|
||||
pub struct SupertraitAsDerefTargetLabel {
|
||||
#[primary_span]
|
||||
pub label: Span,
|
||||
|
@ -38,7 +38,7 @@ pub struct QueryInfo {
|
||||
pub type QueryMap = FxHashMap<QueryJobId, QueryJobInfo>;
|
||||
|
||||
/// A value uniquely identifying an active query job.
|
||||
#[derive(Copy, Clone, Eq, PartialEq, Hash)]
|
||||
#[derive(Copy, Clone, Eq, PartialEq, Hash, Debug)]
|
||||
pub struct QueryJobId(pub NonZeroU64);
|
||||
|
||||
impl QueryJobId {
|
||||
@ -62,14 +62,14 @@ impl QueryJobId {
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone)]
|
||||
#[derive(Clone, Debug)]
|
||||
pub struct QueryJobInfo {
|
||||
pub query: QueryStackFrame,
|
||||
pub job: QueryJob,
|
||||
}
|
||||
|
||||
/// Represents an active query job.
|
||||
#[derive(Clone)]
|
||||
#[derive(Clone, Debug)]
|
||||
pub struct QueryJob {
|
||||
pub id: QueryJobId,
|
||||
|
||||
@ -182,6 +182,7 @@ impl QueryJobId {
|
||||
}
|
||||
|
||||
#[cfg(parallel_compiler)]
|
||||
#[derive(Debug)]
|
||||
struct QueryWaiter {
|
||||
query: Option<QueryJobId>,
|
||||
condvar: Condvar,
|
||||
@ -198,13 +199,14 @@ impl QueryWaiter {
|
||||
}
|
||||
|
||||
#[cfg(parallel_compiler)]
|
||||
#[derive(Debug)]
|
||||
struct QueryLatchInfo {
|
||||
complete: bool,
|
||||
waiters: Vec<Arc<QueryWaiter>>,
|
||||
}
|
||||
|
||||
#[cfg(parallel_compiler)]
|
||||
#[derive(Clone)]
|
||||
#[derive(Clone, Debug)]
|
||||
pub(super) struct QueryLatch {
|
||||
info: Arc<Mutex<QueryLatchInfo>>,
|
||||
}
|
||||
@ -540,7 +542,11 @@ pub fn deadlock(query_map: QueryMap, registry: &rayon_core::Registry) {
|
||||
// X to Y due to Rayon waiting and a true dependency from Y to X. The algorithm here
|
||||
// only considers the true dependency and won't detect a cycle.
|
||||
if !found_cycle {
|
||||
panic!("deadlock detected");
|
||||
if query_map.len() == 0 {
|
||||
panic!("deadlock detected without any query!")
|
||||
} else {
|
||||
panic!("deadlock detected! current query map:\n{:#?}", query_map);
|
||||
}
|
||||
}
|
||||
|
||||
// FIXME: Ensure this won't cause a deadlock before we return
|
||||
|
@ -203,7 +203,7 @@ where
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone)]
|
||||
#[derive(Clone, Debug)]
|
||||
pub(crate) struct CycleError {
|
||||
/// The query and related span that uses the cycle.
|
||||
pub usage: Option<(Span, QueryStackFrame)>,
|
||||
|
@ -1,9 +0,0 @@
|
||||
// compile-flags: --crate-type=lib
|
||||
|
||||
#[derive(Default)] //~ ERROR multiple declared defaults
|
||||
enum E {
|
||||
#[default]
|
||||
A,
|
||||
#[default]
|
||||
A, //~ ERROR defined multiple times
|
||||
}
|
@ -1,29 +0,0 @@
|
||||
error: multiple declared defaults
|
||||
--> $DIR/issue-105101.rs:3:10
|
||||
|
|
||||
LL | #[derive(Default)]
|
||||
| ^^^^^^^
|
||||
...
|
||||
LL | A,
|
||||
| - first default
|
||||
LL | #[default]
|
||||
LL | A,
|
||||
| - additional default
|
||||
|
|
||||
= note: only one variant can be default
|
||||
= note: this error originates in the derive macro `Default` (in Nightly builds, run with -Z macro-backtrace for more info)
|
||||
|
||||
error[E0428]: the name `A` is defined multiple times
|
||||
--> $DIR/issue-105101.rs:8:5
|
||||
|
|
||||
LL | A,
|
||||
| - previous definition of the type `A` here
|
||||
LL | #[default]
|
||||
LL | A,
|
||||
| ^ `A` redefined here
|
||||
|
|
||||
= note: `A` must be defined only once in the type namespace of this enum
|
||||
|
||||
error: aborting due to 2 previous errors
|
||||
|
||||
For more information about this error, try `rustc --explain E0428`.
|
41
tests/ui/deriving/multiple-defaults.rs
Normal file
41
tests/ui/deriving/multiple-defaults.rs
Normal file
@ -0,0 +1,41 @@
|
||||
// compile-flags: --crate-type=lib
|
||||
|
||||
// When we get multiple `#[default]` variants, we emit several tool-only suggestions
|
||||
// to remove all except one of the `#[default]`s.
|
||||
|
||||
#[derive(Default)] //~ ERROR multiple declared defaults
|
||||
enum A {
|
||||
#[default] //~ HELP make `B` default
|
||||
#[default] //~ HELP make `A` default
|
||||
A,
|
||||
#[default] // also "HELP make `A` default", but compiletest can't handle multispans
|
||||
B,
|
||||
}
|
||||
|
||||
// Originally, we took each defaulted variant and emitted the suggestion for every variant
|
||||
// with a different identifier, causing an ICE when multiple variants have the same identifier:
|
||||
// https://github.com/rust-lang/rust/pull/105106
|
||||
#[derive(Default)] //~ ERROR multiple declared defaults
|
||||
enum E {
|
||||
#[default] //~ HELP make `A` default
|
||||
A,
|
||||
#[default] //~ HELP make `A` default
|
||||
A, //~ ERROR defined multiple times
|
||||
}
|
||||
|
||||
// Then, we took each defaulted variant and emitted the suggestion for every variant
|
||||
// with a different span, causing an ICE when multiple variants have the same span:
|
||||
// https://github.com/rust-lang/rust/issues/118119
|
||||
macro_rules! m {
|
||||
{ $($id:ident)* } => {
|
||||
#[derive(Default)] //~ ERROR multiple declared defaults
|
||||
enum F {
|
||||
$(
|
||||
#[default]
|
||||
$id,
|
||||
)*
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
m! { A B }
|
62
tests/ui/deriving/multiple-defaults.stderr
Normal file
62
tests/ui/deriving/multiple-defaults.stderr
Normal file
@ -0,0 +1,62 @@
|
||||
error: multiple declared defaults
|
||||
--> $DIR/multiple-defaults.rs:6:10
|
||||
|
|
||||
LL | #[derive(Default)]
|
||||
| ^^^^^^^
|
||||
...
|
||||
LL | A,
|
||||
| - first default
|
||||
LL | #[default] // also "HELP make `A` default", but compiletest can't handle multispans
|
||||
LL | B,
|
||||
| - additional default
|
||||
|
|
||||
= note: only one variant can be default
|
||||
= 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/multiple-defaults.rs:18:10
|
||||
|
|
||||
LL | #[derive(Default)]
|
||||
| ^^^^^^^
|
||||
...
|
||||
LL | A,
|
||||
| - first default
|
||||
LL | #[default]
|
||||
LL | A,
|
||||
| - additional default
|
||||
|
|
||||
= note: only one variant can be default
|
||||
= note: this error originates in the derive macro `Default` (in Nightly builds, run with -Z macro-backtrace for more info)
|
||||
|
||||
error[E0428]: the name `A` is defined multiple times
|
||||
--> $DIR/multiple-defaults.rs:23:5
|
||||
|
|
||||
LL | A,
|
||||
| - previous definition of the type `A` here
|
||||
LL | #[default]
|
||||
LL | A,
|
||||
| ^ `A` redefined here
|
||||
|
|
||||
= note: `A` must be defined only once in the type namespace of this enum
|
||||
|
||||
error: multiple declared defaults
|
||||
--> $DIR/multiple-defaults.rs:31:18
|
||||
|
|
||||
LL | #[derive(Default)]
|
||||
| ^^^^^^^
|
||||
...
|
||||
LL | $id,
|
||||
| ---
|
||||
| |
|
||||
| first default
|
||||
| additional default
|
||||
...
|
||||
LL | m! { A B }
|
||||
| ---------- in this macro invocation
|
||||
|
|
||||
= note: only one variant can be default
|
||||
= note: this error originates in the derive macro `Default` which comes from the expansion of the macro `m` (in Nightly builds, run with -Z macro-backtrace for more info)
|
||||
|
||||
error: aborting due to 4 previous errors
|
||||
|
||||
For more information about this error, try `rustc --explain E0428`.
|
@ -2,7 +2,7 @@ warning: this `Deref` implementation is covered by an implicit supertrait coerci
|
||||
--> $DIR/deref-lint-regions.rs:8:1
|
||||
|
|
||||
LL | impl<'a> Deref for dyn Foo<'a> {
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `dyn Foo<'_>` implements `Deref<Target = dyn Bar<'_>>` which conflicts with supertrait `Bar<'_>`
|
||||
LL |
|
||||
LL | type Target = dyn Bar<'a>;
|
||||
| -------------------------- target type is a supertrait of `dyn Foo<'_>`
|
||||
|
@ -8,6 +8,7 @@ trait B: A {}
|
||||
|
||||
impl<'a> Deref for dyn 'a + B {
|
||||
//~^ WARN this `Deref` implementation is covered by an implicit supertrait coercion
|
||||
|
||||
type Target = dyn A;
|
||||
fn deref(&self) -> &Self::Target {
|
||||
todo!()
|
||||
|
@ -2,8 +2,8 @@ warning: this `Deref` implementation is covered by an implicit supertrait coerci
|
||||
--> $DIR/deref-lint.rs:9:1
|
||||
|
|
||||
LL | impl<'a> Deref for dyn 'a + B {
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
LL |
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `dyn B` implements `Deref<Target = dyn A>` which conflicts with supertrait `A`
|
||||
...
|
||||
LL | type Target = dyn A;
|
||||
| -------------------- target type is a supertrait of `dyn B`
|
||||
|
|
||||
|
@ -0,0 +1,34 @@
|
||||
#![deny(deref_into_dyn_supertrait)]
|
||||
use std::ops::Deref;
|
||||
|
||||
trait Bar<T> {}
|
||||
impl<T, U> Bar<U> for T {}
|
||||
|
||||
trait Foo: Bar<i32> {
|
||||
fn as_dyn_bar_u32<'a>(&self) -> &(dyn Bar<u32> + 'a);
|
||||
}
|
||||
|
||||
impl Foo for () {
|
||||
fn as_dyn_bar_u32<'a>(&self) -> &(dyn Bar<u32> + 'a) {
|
||||
self
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> Deref for dyn Foo + 'a {
|
||||
type Target = dyn Bar<u32> + 'a;
|
||||
|
||||
fn deref(&self) -> &Self::Target {
|
||||
self.as_dyn_bar_u32()
|
||||
}
|
||||
}
|
||||
|
||||
fn take_dyn<T>(x: &dyn Bar<T>) -> T {
|
||||
todo!()
|
||||
}
|
||||
|
||||
fn main() {
|
||||
let x: &dyn Foo = &();
|
||||
let y = take_dyn(x);
|
||||
let z: u32 = y;
|
||||
//~^ ERROR mismatched types
|
||||
}
|
@ -0,0 +1,16 @@
|
||||
error[E0308]: mismatched types
|
||||
--> $DIR/deref-upcast-behavioral-change.rs:32:18
|
||||
|
|
||||
LL | let z: u32 = y;
|
||||
| --- ^ expected `u32`, found `i32`
|
||||
| |
|
||||
| expected due to this
|
||||
|
|
||||
help: you can convert an `i32` to a `u32` and panic if the converted value doesn't fit
|
||||
|
|
||||
LL | let z: u32 = y.try_into().unwrap();
|
||||
| ++++++++++++++++++++
|
||||
|
||||
error: aborting due to previous error
|
||||
|
||||
For more information about this error, try `rustc --explain E0308`.
|
@ -0,0 +1,20 @@
|
||||
// check-pass
|
||||
|
||||
use std::ops::Deref;
|
||||
|
||||
trait Bar<T> {}
|
||||
|
||||
trait Foo: Bar<i32> {
|
||||
fn as_dyn_bar_u32<'a>(&self) -> &(dyn Bar<u32> + 'a);
|
||||
}
|
||||
|
||||
impl<'a> Deref for dyn Foo + 'a {
|
||||
//~^ WARN this `Deref` implementation is covered by an implicit supertrait coercion
|
||||
type Target = dyn Bar<u32> + 'a;
|
||||
|
||||
fn deref(&self) -> &Self::Target {
|
||||
self.as_dyn_bar_u32()
|
||||
}
|
||||
}
|
||||
|
||||
fn main() {}
|
@ -0,0 +1,14 @@
|
||||
warning: this `Deref` implementation is covered by an implicit supertrait coercion
|
||||
--> $DIR/migrate-lint-different-substs.rs:11:1
|
||||
|
|
||||
LL | impl<'a> Deref for dyn Foo + 'a {
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `dyn Foo` implements `Deref<Target = dyn Bar<u32>>` which conflicts with supertrait `Bar<i32>`
|
||||
LL |
|
||||
LL | type Target = dyn Bar<u32> + 'a;
|
||||
| -------------------------------- target type is a supertrait of `dyn Foo`
|
||||
|
|
||||
= help: consider removing this implementation or replacing it with a method instead
|
||||
= note: `#[warn(deref_into_dyn_supertrait)]` on by default
|
||||
|
||||
warning: 1 warning emitted
|
||||
|
Loading…
x
Reference in New Issue
Block a user