From 5ac973426eb1f6b3dd9b883daedbfe71f27da704 Mon Sep 17 00:00:00 2001 From: lcnr Date: Wed, 23 Mar 2022 10:06:29 +0100 Subject: [PATCH] rewrite `ensure_drop_params_and_item_params_correspond` --- compiler/rustc_typeck/src/check/dropck.rs | 99 +++++-------------- compiler/rustc_typeck/src/coherence/orphan.rs | 18 ++-- .../auto-traits/suspicious-impls-lint.stderr | 10 +- src/test/ui/dropck/issue-38868.stderr | 1 + .../dropck/reject-specialized-drops-8142.rs | 6 +- .../reject-specialized-drops-8142.stderr | 63 +++++------- 6 files changed, 71 insertions(+), 126 deletions(-) diff --git a/compiler/rustc_typeck/src/check/dropck.rs b/compiler/rustc_typeck/src/check/dropck.rs index 9caa4a40df7..0b0f7a085fc 100644 --- a/compiler/rustc_typeck/src/check/dropck.rs +++ b/compiler/rustc_typeck/src/check/dropck.rs @@ -2,17 +2,13 @@ use crate::check::regionck::RegionCtxt; use crate::hir; use crate::hir::def_id::{DefId, LocalDefId}; use rustc_errors::{struct_span_err, ErrorGuaranteed}; -use rustc_infer::infer::outlives::env::OutlivesEnvironment; -use rustc_infer::infer::{InferOk, RegionckMode, TyCtxtInferExt}; -use rustc_infer::traits::TraitEngineExt as _; use rustc_middle::ty::error::TypeError; use rustc_middle::ty::relate::{Relate, RelateResult, TypeRelation}; -use rustc_middle::ty::subst::{Subst, SubstsRef}; -use rustc_middle::ty::{self, EarlyBinder, Predicate, Ty, TyCtxt}; +use rustc_middle::ty::subst::SubstsRef; +use rustc_middle::ty::{self, Predicate, Ty, TyCtxt}; use rustc_span::Span; -use rustc_trait_selection::traits::error_reporting::InferCtxtExt; use rustc_trait_selection::traits::query::dropck_outlives::AtExt; -use rustc_trait_selection::traits::{ObligationCause, TraitEngine, TraitEngineExt}; +use rustc_trait_selection::traits::ObligationCause; /// This function confirms that the `Drop` implementation identified by /// `drop_impl_did` is not any more specialized than the type it is @@ -39,8 +35,8 @@ pub fn check_drop_impl(tcx: TyCtxt<'_>, drop_impl_did: DefId) -> Result<(), Erro ensure_drop_params_and_item_params_correspond( tcx, drop_impl_did.expect_local(), - dtor_self_type, adt_def.did(), + self_to_impl_substs, )?; ensure_drop_predicates_are_implied_by_item_defn( @@ -67,75 +63,34 @@ pub fn check_drop_impl(tcx: TyCtxt<'_>, drop_impl_did: DefId) -> Result<(), Erro fn ensure_drop_params_and_item_params_correspond<'tcx>( tcx: TyCtxt<'tcx>, drop_impl_did: LocalDefId, - drop_impl_ty: Ty<'tcx>, self_type_did: DefId, + drop_impl_substs: SubstsRef<'tcx>, ) -> Result<(), ErrorGuaranteed> { - let drop_impl_hir_id = tcx.hir().local_def_id_to_hir_id(drop_impl_did); + let Err(arg) = tcx.uses_unique_generic_params(drop_impl_substs, false) else { + return Ok(()) + }; - // check that the impl type can be made to match the trait type. - - tcx.infer_ctxt().enter(|ref infcx| { - let impl_param_env = tcx.param_env(self_type_did); - let tcx = infcx.tcx; - let mut fulfillment_cx = >::new(tcx); - - let named_type = tcx.type_of(self_type_did); - - let drop_impl_span = tcx.def_span(drop_impl_did); - let fresh_impl_substs = - infcx.fresh_substs_for_item(drop_impl_span, drop_impl_did.to_def_id()); - let fresh_impl_self_ty = EarlyBinder(drop_impl_ty).subst(tcx, fresh_impl_substs); - - let cause = &ObligationCause::misc(drop_impl_span, drop_impl_hir_id); - match infcx.at(cause, impl_param_env).eq(named_type, fresh_impl_self_ty) { - Ok(InferOk { obligations, .. }) => { - fulfillment_cx.register_predicate_obligations(infcx, obligations); - } - Err(_) => { - let item_span = tcx.def_span(self_type_did); - let self_descr = tcx.def_kind(self_type_did).descr(self_type_did); - let reported = struct_span_err!( - tcx.sess, - drop_impl_span, - E0366, - "`Drop` impls cannot be specialized" - ) - .span_note( - item_span, - &format!( - "use the same sequence of generic type, lifetime and const parameters \ - as the {self_descr} definition", - ), - ) - .emit(); - return Err(reported); - } + let drop_impl_span = tcx.def_span(drop_impl_did); + let item_span = tcx.def_span(self_type_did); + let self_descr = tcx.def_kind(self_type_did).descr(self_type_did); + let mut err = + struct_span_err!(tcx.sess, drop_impl_span, E0366, "`Drop` impls cannot be specialized"); + match arg { + ty::util::NotUniqueParam::DuplicateParam(arg) => { + err.note(&format!("`{arg}` is mentioned multiple times")) } - - let errors = fulfillment_cx.select_all_or_error(&infcx); - if !errors.is_empty() { - // this could be reached when we get lazy normalization - let reported = infcx.report_fulfillment_errors(&errors, None, false); - return Err(reported); + ty::util::NotUniqueParam::NotParam(arg) => { + err.note(&format!("`{arg}` is not a generic parameter")) } - - // NB. It seems a bit... suspicious to use an empty param-env - // here. The correct thing, I imagine, would be - // `OutlivesEnvironment::new(impl_param_env)`, which would - // allow region solving to take any `a: 'b` relations on the - // impl into account. But I could not create a test case where - // it did the wrong thing, so I chose to preserve existing - // behavior, since it ought to be simply more - // conservative. -nmatsakis - let outlives_env = OutlivesEnvironment::new(ty::ParamEnv::empty()); - - infcx.resolve_regions_and_report_errors( - drop_impl_did.to_def_id(), - &outlives_env, - RegionckMode::default(), - ); - Ok(()) - }) + }; + err.span_note( + item_span, + &format!( + "use the same sequence of generic type, lifetime and const parameters \ + as the {self_descr} definition", + ), + ); + Err(err.emit()) } /// Confirms that every predicate imposed by dtor_predicates is diff --git a/compiler/rustc_typeck/src/coherence/orphan.rs b/compiler/rustc_typeck/src/coherence/orphan.rs index ad8a84d536f..f8b3f1ac3df 100644 --- a/compiler/rustc_typeck/src/coherence/orphan.rs +++ b/compiler/rustc_typeck/src/coherence/orphan.rs @@ -383,20 +383,13 @@ fn lint_auto_trait_impls(tcx: TyCtxt<'_>, trait_def_id: DefId, impls: &[LocalDef tcx.hir().local_def_id_to_hir_id(impl_def_id), tcx.def_span(impl_def_id), |err| { + let item_span = tcx.def_span(self_type_did); + let self_descr = tcx.def_kind(self_type_did).descr(self_type_did); let mut err = err.build(&format!( "cross-crate traits with a default impl, like `{}`, \ should not be specialized", tcx.def_path_str(trait_def_id), )); - let item_span = tcx.def_span(self_type_did); - let self_descr = tcx.def_kind(self_type_did).descr(self_type_did); - err.span_note( - item_span, - &format!( - "try using the same sequence of generic parameters as the {} definition", - self_descr, - ), - ); match arg { ty::util::NotUniqueParam::DuplicateParam(arg) => { err.note(&format!("`{}` is mentioned multiple times", arg)); @@ -405,6 +398,13 @@ fn lint_auto_trait_impls(tcx: TyCtxt<'_>, trait_def_id: DefId, impls: &[LocalDef err.note(&format!("`{}` is not a generic parameter", arg)); } } + err.span_note( + item_span, + &format!( + "try using the same sequence of generic parameters as the {} definition", + self_descr, + ), + ); err.emit(); }, ); diff --git a/src/test/ui/auto-traits/suspicious-impls-lint.stderr b/src/test/ui/auto-traits/suspicious-impls-lint.stderr index e299e5369fe..03460b28dcd 100644 --- a/src/test/ui/auto-traits/suspicious-impls-lint.stderr +++ b/src/test/ui/auto-traits/suspicious-impls-lint.stderr @@ -11,12 +11,12 @@ LL | #![deny(suspicious_auto_trait_impls)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ = warning: this will change its meaning in a future release! = note: for more information, see issue #93367 + = note: `&T` is not a generic parameter note: try using the same sequence of generic parameters as the struct definition --> $DIR/suspicious-impls-lint.rs:8:1 | LL | struct MayImplementSendErr(T); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - = note: `&T` is not a generic parameter error: cross-crate traits with a default impl, like `Send`, should not be specialized --> $DIR/suspicious-impls-lint.rs:21:1 @@ -26,12 +26,12 @@ LL | unsafe impl Send for ContainsVec {} | = warning: this will change its meaning in a future release! = note: for more information, see issue #93367 + = note: `i32` is not a generic parameter note: try using the same sequence of generic parameters as the struct definition --> $DIR/suspicious-impls-lint.rs:20:1 | LL | struct ContainsVec(Vec); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - = note: `i32` is not a generic parameter error: cross-crate traits with a default impl, like `Send`, should not be specialized --> $DIR/suspicious-impls-lint.rs:32:1 @@ -41,12 +41,12 @@ LL | unsafe impl Send for TwoParamsSame {} | = warning: this will change its meaning in a future release! = note: for more information, see issue #93367 + = note: `T` is mentioned multiple times note: try using the same sequence of generic parameters as the struct definition --> $DIR/suspicious-impls-lint.rs:31:1 | LL | struct TwoParamsSame(T, U); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - = note: `T` is mentioned multiple times error: cross-crate traits with a default impl, like `Send`, should not be specialized --> $DIR/suspicious-impls-lint.rs:40:1 @@ -56,12 +56,12 @@ LL | unsafe impl Send for WithPhantomDataSend<*const T, i8> {} | = warning: this will change its meaning in a future release! = note: for more information, see issue #93367 + = note: `*const T` is not a generic parameter note: try using the same sequence of generic parameters as the struct definition --> $DIR/suspicious-impls-lint.rs:39:1 | LL | pub struct WithPhantomDataSend(PhantomData, U); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - = note: `*const T` is not a generic parameter error: cross-crate traits with a default impl, like `Sync`, should not be specialized --> $DIR/suspicious-impls-lint.rs:46:1 @@ -71,12 +71,12 @@ LL | unsafe impl Sync for WithLifetime<'static, Vec> {} | = warning: this will change its meaning in a future release! = note: for more information, see issue #93367 + = note: `Vec` is not a generic parameter note: try using the same sequence of generic parameters as the struct definition --> $DIR/suspicious-impls-lint.rs:44:1 | LL | pub struct WithLifetime<'a, T>(&'a (), T); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - = note: `Vec` is not a generic parameter error: aborting due to 5 previous errors diff --git a/src/test/ui/dropck/issue-38868.stderr b/src/test/ui/dropck/issue-38868.stderr index 10d1e7c4e66..f369b74cf55 100644 --- a/src/test/ui/dropck/issue-38868.stderr +++ b/src/test/ui/dropck/issue-38868.stderr @@ -8,6 +8,7 @@ LL | | } LL | | } | |_^ | + = note: `i32` is not a generic parameter note: use the same sequence of generic type, lifetime and const parameters as the struct definition --> $DIR/issue-38868.rs:1:1 | diff --git a/src/test/ui/dropck/reject-specialized-drops-8142.rs b/src/test/ui/dropck/reject-specialized-drops-8142.rs index c9599f6e805..7a3bbe7cb09 100644 --- a/src/test/ui/dropck/reject-specialized-drops-8142.rs +++ b/src/test/ui/dropck/reject-specialized-drops-8142.rs @@ -32,9 +32,7 @@ impl<'al,'adds_bnd> Drop for L<'al,'adds_bnd> where 'adds_bnd:'al { // RE impl<'ml> Drop for M<'ml> { fn drop(&mut self) { } } // ACCEPT impl Drop for N<'static> { fn drop(&mut self) { } } // REJECT -//~^ ERROR mismatched types -//~| expected struct `N<'n>` -//~| found struct `N<'static>` +//~^ ERROR `Drop` impls cannot be specialized impl Drop for O { fn drop(&mut self) { } } // ACCEPT @@ -57,7 +55,7 @@ impl Drop for V { fn drop(&mut self) { } } // REJECT //~^ ERROR `Drop` impls cannot be specialized impl<'lw> Drop for W<'lw,'lw> { fn drop(&mut self) { } } // REJECT -//~^ ERROR cannot infer an appropriate lifetime for lifetime parameter `'lw` +//~^ ERROR `Drop` impls cannot be specialized impl Drop for X<3> { fn drop(&mut self) { } } // REJECT //~^ ERROR `Drop` impls cannot be specialized diff --git a/src/test/ui/dropck/reject-specialized-drops-8142.stderr b/src/test/ui/dropck/reject-specialized-drops-8142.stderr index 8dbde9d417d..82e95ea075d 100644 --- a/src/test/ui/dropck/reject-specialized-drops-8142.stderr +++ b/src/test/ui/dropck/reject-specialized-drops-8142.stderr @@ -22,27 +22,26 @@ note: the implementor must specify the same requirement LL | struct L<'l1,'l2> { x: &'l1 i8, y: &'l2 u8 } | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -error[E0308]: mismatched types +error[E0366]: `Drop` impls cannot be specialized --> $DIR/reject-specialized-drops-8142.rs:34:1 | LL | impl Drop for N<'static> { fn drop(&mut self) { } } // REJECT - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ lifetime mismatch + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | - = note: expected struct `N<'n>` - found struct `N<'static>` -note: the lifetime `'n` as defined here... - --> $DIR/reject-specialized-drops-8142.rs:7:10 + = note: `'static` is not a generic parameter +note: use the same sequence of generic type, lifetime and const parameters as the struct definition + --> $DIR/reject-specialized-drops-8142.rs:7:1 | LL | struct N<'n> { x: &'n i8 } - | ^^ - = note: ...does not necessarily outlive the static lifetime + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ error[E0366]: `Drop` impls cannot be specialized - --> $DIR/reject-specialized-drops-8142.rs:41:1 + --> $DIR/reject-specialized-drops-8142.rs:39:1 | LL | impl Drop for P { fn drop(&mut self) { } } // REJECT | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | + = note: `i8` is not a generic parameter note: use the same sequence of generic type, lifetime and const parameters as the struct definition --> $DIR/reject-specialized-drops-8142.rs:9:1 | @@ -50,7 +49,7 @@ LL | struct P { x: *const Tp } | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error[E0367]: `Drop` impl requires `AddsBnd: Bound` but the struct it is implemented for does not - --> $DIR/reject-specialized-drops-8142.rs:44:14 + --> $DIR/reject-specialized-drops-8142.rs:42:14 | LL | impl Drop for Q { fn drop(&mut self) { } } // REJECT | ^^^^^ @@ -62,7 +61,7 @@ LL | struct Q { x: *const Tq } | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error[E0367]: `Drop` impl requires `AddsRBnd: 'rbnd` but the struct it is implemented for does not - --> $DIR/reject-specialized-drops-8142.rs:47:21 + --> $DIR/reject-specialized-drops-8142.rs:45:21 | LL | impl<'rbnd,AddsRBnd:'rbnd> Drop for R { fn drop(&mut self) { } } // REJECT | ^^^^^ @@ -74,47 +73,38 @@ LL | struct R { x: *const Tr } | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error[E0366]: `Drop` impls cannot be specialized - --> $DIR/reject-specialized-drops-8142.rs:56:1 + --> $DIR/reject-specialized-drops-8142.rs:54:1 | LL | impl Drop for V { fn drop(&mut self) { } } // REJECT | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | + = note: `One` is mentioned multiple times note: use the same sequence of generic type, lifetime and const parameters as the struct definition --> $DIR/reject-specialized-drops-8142.rs:15:1 | LL | struct V { x: *const Tva, y: *const Tvb } | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -error[E0495]: cannot infer an appropriate lifetime for lifetime parameter `'lw` due to conflicting requirements - --> $DIR/reject-specialized-drops-8142.rs:59:1 +error[E0366]: `Drop` impls cannot be specialized + --> $DIR/reject-specialized-drops-8142.rs:57:1 | LL | impl<'lw> Drop for W<'lw,'lw> { fn drop(&mut self) { } } // REJECT | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | -note: first, the lifetime cannot outlive the lifetime `'l1` as defined here... - --> $DIR/reject-specialized-drops-8142.rs:16:10 + = note: `'lw` is mentioned multiple times +note: use the same sequence of generic type, lifetime and const parameters as the struct definition + --> $DIR/reject-specialized-drops-8142.rs:16:1 | LL | struct W<'l1, 'l2> { x: &'l1 i8, y: &'l2 u8 } - | ^^^ -note: ...but the lifetime must also be valid for the lifetime `'l2` as defined here... - --> $DIR/reject-specialized-drops-8142.rs:16:15 - | -LL | struct W<'l1, 'l2> { x: &'l1 i8, y: &'l2 u8 } - | ^^^ -note: ...so that the types are compatible - --> $DIR/reject-specialized-drops-8142.rs:59:1 - | -LL | impl<'lw> Drop for W<'lw,'lw> { fn drop(&mut self) { } } // REJECT - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - = note: expected `W<'l1, 'l2>` - found `W<'_, '_>` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error[E0366]: `Drop` impls cannot be specialized - --> $DIR/reject-specialized-drops-8142.rs:62:1 + --> $DIR/reject-specialized-drops-8142.rs:60:1 | LL | impl Drop for X<3> { fn drop(&mut self) { } } // REJECT | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | + = note: `3_usize` is not a generic parameter note: use the same sequence of generic type, lifetime and const parameters as the struct definition --> $DIR/reject-specialized-drops-8142.rs:17:1 | @@ -122,11 +112,12 @@ LL | struct X; | ^^^^^^^^^^^^^^^^^^^^^^^^^^ error[E0366]: `Drop` impls cannot be specialized - --> $DIR/reject-specialized-drops-8142.rs:65:1 + --> $DIR/reject-specialized-drops-8142.rs:63:1 | LL | impl Drop for Y { fn drop(&mut self) { } } // REJECT | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | + = note: `Ca` is mentioned multiple times note: use the same sequence of generic type, lifetime and const parameters as the struct definition --> $DIR/reject-specialized-drops-8142.rs:18:1 | @@ -134,7 +125,7 @@ LL | struct Y; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error[E0367]: `Drop` impl requires `AddsBnd: Bound` but the enum it is implemented for does not - --> $DIR/reject-specialized-drops-8142.rs:68:14 + --> $DIR/reject-specialized-drops-8142.rs:66:14 | LL | impl Drop for Enum { fn drop(&mut self) { } } // REJECT | ^^^^^ @@ -146,7 +137,7 @@ LL | enum Enum { Variant(T) } | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ error[E0367]: `Drop` impl requires `AddsBnd: Bound` but the struct it is implemented for does not - --> $DIR/reject-specialized-drops-8142.rs:71:14 + --> $DIR/reject-specialized-drops-8142.rs:69:14 | LL | impl Drop for TupleStruct { fn drop(&mut self) { } } // REJECT | ^^^^^ @@ -158,7 +149,7 @@ LL | struct TupleStruct(T); | ^^^^^^^^^^^^^^^^^^^^^^^^^ error[E0367]: `Drop` impl requires `AddsBnd: Bound` but the union it is implemented for does not - --> $DIR/reject-specialized-drops-8142.rs:74:21 + --> $DIR/reject-specialized-drops-8142.rs:72:21 | LL | impl Drop for Union { fn drop(&mut self) { } } // REJECT | ^^^^^ @@ -171,5 +162,5 @@ LL | union Union { f: T } error: aborting due to 13 previous errors -Some errors have detailed explanations: E0308, E0366, E0367, E0495. -For more information about an error, try `rustc --explain E0308`. +Some errors have detailed explanations: E0366, E0367. +For more information about an error, try `rustc --explain E0366`.