Skip to content

Commit 5ac9734

Browse files
committed
rewrite ensure_drop_params_and_item_params_correspond
1 parent f3f6832 commit 5ac9734

File tree

6 files changed

+72
-127
lines changed

6 files changed

+72
-127
lines changed

compiler/rustc_typeck/src/check/dropck.rs

Lines changed: 28 additions & 73 deletions
Original file line numberDiff line numberDiff line change
@@ -2,17 +2,13 @@ use crate::check::regionck::RegionCtxt;
22
use crate::hir;
33
use crate::hir::def_id::{DefId, LocalDefId};
44
use rustc_errors::{struct_span_err, ErrorGuaranteed};
5-
use rustc_infer::infer::outlives::env::OutlivesEnvironment;
6-
use rustc_infer::infer::{InferOk, RegionckMode, TyCtxtInferExt};
7-
use rustc_infer::traits::TraitEngineExt as _;
85
use rustc_middle::ty::error::TypeError;
96
use rustc_middle::ty::relate::{Relate, RelateResult, TypeRelation};
10-
use rustc_middle::ty::subst::{Subst, SubstsRef};
11-
use rustc_middle::ty::{self, EarlyBinder, Predicate, Ty, TyCtxt};
7+
use rustc_middle::ty::subst::SubstsRef;
8+
use rustc_middle::ty::{self, Predicate, Ty, TyCtxt};
129
use rustc_span::Span;
13-
use rustc_trait_selection::traits::error_reporting::InferCtxtExt;
1410
use rustc_trait_selection::traits::query::dropck_outlives::AtExt;
15-
use rustc_trait_selection::traits::{ObligationCause, TraitEngine, TraitEngineExt};
11+
use rustc_trait_selection::traits::ObligationCause;
1612

1713
/// This function confirms that the `Drop` implementation identified by
1814
/// `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
3935
ensure_drop_params_and_item_params_correspond(
4036
tcx,
4137
drop_impl_did.expect_local(),
42-
dtor_self_type,
4338
adt_def.did(),
39+
self_to_impl_substs,
4440
)?;
4541

4642
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
6763
fn ensure_drop_params_and_item_params_correspond<'tcx>(
6864
tcx: TyCtxt<'tcx>,
6965
drop_impl_did: LocalDefId,
70-
drop_impl_ty: Ty<'tcx>,
7166
self_type_did: DefId,
67+
drop_impl_substs: SubstsRef<'tcx>,
7268
) -> Result<(), ErrorGuaranteed> {
73-
let drop_impl_hir_id = tcx.hir().local_def_id_to_hir_id(drop_impl_did);
74-
75-
// check that the impl type can be made to match the trait type.
76-
77-
tcx.infer_ctxt().enter(|ref infcx| {
78-
let impl_param_env = tcx.param_env(self_type_did);
79-
let tcx = infcx.tcx;
80-
let mut fulfillment_cx = <dyn TraitEngine<'_>>::new(tcx);
81-
82-
let named_type = tcx.type_of(self_type_did);
83-
84-
let drop_impl_span = tcx.def_span(drop_impl_did);
85-
let fresh_impl_substs =
86-
infcx.fresh_substs_for_item(drop_impl_span, drop_impl_did.to_def_id());
87-
let fresh_impl_self_ty = EarlyBinder(drop_impl_ty).subst(tcx, fresh_impl_substs);
88-
89-
let cause = &ObligationCause::misc(drop_impl_span, drop_impl_hir_id);
90-
match infcx.at(cause, impl_param_env).eq(named_type, fresh_impl_self_ty) {
91-
Ok(InferOk { obligations, .. }) => {
92-
fulfillment_cx.register_predicate_obligations(infcx, obligations);
93-
}
94-
Err(_) => {
95-
let item_span = tcx.def_span(self_type_did);
96-
let self_descr = tcx.def_kind(self_type_did).descr(self_type_did);
97-
let reported = struct_span_err!(
98-
tcx.sess,
99-
drop_impl_span,
100-
E0366,
101-
"`Drop` impls cannot be specialized"
102-
)
103-
.span_note(
104-
item_span,
105-
&format!(
106-
"use the same sequence of generic type, lifetime and const parameters \
107-
as the {self_descr} definition",
108-
),
109-
)
110-
.emit();
111-
return Err(reported);
112-
}
69+
let Err(arg) = tcx.uses_unique_generic_params(drop_impl_substs, false) else {
70+
return Ok(())
71+
};
72+
73+
let drop_impl_span = tcx.def_span(drop_impl_did);
74+
let item_span = tcx.def_span(self_type_did);
75+
let self_descr = tcx.def_kind(self_type_did).descr(self_type_did);
76+
let mut err =
77+
struct_span_err!(tcx.sess, drop_impl_span, E0366, "`Drop` impls cannot be specialized");
78+
match arg {
79+
ty::util::NotUniqueParam::DuplicateParam(arg) => {
80+
err.note(&format!("`{arg}` is mentioned multiple times"))
11381
}
114-
115-
let errors = fulfillment_cx.select_all_or_error(&infcx);
116-
if !errors.is_empty() {
117-
// this could be reached when we get lazy normalization
118-
let reported = infcx.report_fulfillment_errors(&errors, None, false);
119-
return Err(reported);
82+
ty::util::NotUniqueParam::NotParam(arg) => {
83+
err.note(&format!("`{arg}` is not a generic parameter"))
12084
}
121-
122-
// NB. It seems a bit... suspicious to use an empty param-env
123-
// here. The correct thing, I imagine, would be
124-
// `OutlivesEnvironment::new(impl_param_env)`, which would
125-
// allow region solving to take any `a: 'b` relations on the
126-
// impl into account. But I could not create a test case where
127-
// it did the wrong thing, so I chose to preserve existing
128-
// behavior, since it ought to be simply more
129-
// conservative. -nmatsakis
130-
let outlives_env = OutlivesEnvironment::new(ty::ParamEnv::empty());
131-
132-
infcx.resolve_regions_and_report_errors(
133-
drop_impl_did.to_def_id(),
134-
&outlives_env,
135-
RegionckMode::default(),
136-
);
137-
Ok(())
138-
})
85+
};
86+
err.span_note(
87+
item_span,
88+
&format!(
89+
"use the same sequence of generic type, lifetime and const parameters \
90+
as the {self_descr} definition",
91+
),
92+
);
93+
Err(err.emit())
13994
}
14095

14196
/// Confirms that every predicate imposed by dtor_predicates is

compiler/rustc_typeck/src/coherence/orphan.rs

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -383,20 +383,13 @@ fn lint_auto_trait_impls(tcx: TyCtxt<'_>, trait_def_id: DefId, impls: &[LocalDef
383383
tcx.hir().local_def_id_to_hir_id(impl_def_id),
384384
tcx.def_span(impl_def_id),
385385
|err| {
386+
let item_span = tcx.def_span(self_type_did);
387+
let self_descr = tcx.def_kind(self_type_did).descr(self_type_did);
386388
let mut err = err.build(&format!(
387389
"cross-crate traits with a default impl, like `{}`, \
388390
should not be specialized",
389391
tcx.def_path_str(trait_def_id),
390392
));
391-
let item_span = tcx.def_span(self_type_did);
392-
let self_descr = tcx.def_kind(self_type_did).descr(self_type_did);
393-
err.span_note(
394-
item_span,
395-
&format!(
396-
"try using the same sequence of generic parameters as the {} definition",
397-
self_descr,
398-
),
399-
);
400393
match arg {
401394
ty::util::NotUniqueParam::DuplicateParam(arg) => {
402395
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
405398
err.note(&format!("`{}` is not a generic parameter", arg));
406399
}
407400
}
401+
err.span_note(
402+
item_span,
403+
&format!(
404+
"try using the same sequence of generic parameters as the {} definition",
405+
self_descr,
406+
),
407+
);
408408
err.emit();
409409
},
410410
);

src/test/ui/auto-traits/suspicious-impls-lint.stderr

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -11,12 +11,12 @@ LL | #![deny(suspicious_auto_trait_impls)]
1111
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^
1212
= warning: this will change its meaning in a future release!
1313
= note: for more information, see issue #93367 <https://github.com/rust-lang/rust/issues/93367>
14+
= note: `&T` is not a generic parameter
1415
note: try using the same sequence of generic parameters as the struct definition
1516
--> $DIR/suspicious-impls-lint.rs:8:1
1617
|
1718
LL | struct MayImplementSendErr<T>(T);
1819
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
19-
= note: `&T` is not a generic parameter
2020

2121
error: cross-crate traits with a default impl, like `Send`, should not be specialized
2222
--> $DIR/suspicious-impls-lint.rs:21:1
@@ -26,12 +26,12 @@ LL | unsafe impl Send for ContainsVec<i32> {}
2626
|
2727
= warning: this will change its meaning in a future release!
2828
= note: for more information, see issue #93367 <https://github.com/rust-lang/rust/issues/93367>
29+
= note: `i32` is not a generic parameter
2930
note: try using the same sequence of generic parameters as the struct definition
3031
--> $DIR/suspicious-impls-lint.rs:20:1
3132
|
3233
LL | struct ContainsVec<T>(Vec<T>);
3334
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
34-
= note: `i32` is not a generic parameter
3535

3636
error: cross-crate traits with a default impl, like `Send`, should not be specialized
3737
--> $DIR/suspicious-impls-lint.rs:32:1
@@ -41,12 +41,12 @@ LL | unsafe impl<T: Send> Send for TwoParamsSame<T, T> {}
4141
|
4242
= warning: this will change its meaning in a future release!
4343
= note: for more information, see issue #93367 <https://github.com/rust-lang/rust/issues/93367>
44+
= note: `T` is mentioned multiple times
4445
note: try using the same sequence of generic parameters as the struct definition
4546
--> $DIR/suspicious-impls-lint.rs:31:1
4647
|
4748
LL | struct TwoParamsSame<T, U>(T, U);
4849
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
49-
= note: `T` is mentioned multiple times
5050

5151
error: cross-crate traits with a default impl, like `Send`, should not be specialized
5252
--> $DIR/suspicious-impls-lint.rs:40:1
@@ -56,12 +56,12 @@ LL | unsafe impl<T> Send for WithPhantomDataSend<*const T, i8> {}
5656
|
5757
= warning: this will change its meaning in a future release!
5858
= note: for more information, see issue #93367 <https://github.com/rust-lang/rust/issues/93367>
59+
= note: `*const T` is not a generic parameter
5960
note: try using the same sequence of generic parameters as the struct definition
6061
--> $DIR/suspicious-impls-lint.rs:39:1
6162
|
6263
LL | pub struct WithPhantomDataSend<T, U>(PhantomData<T>, U);
6364
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
64-
= note: `*const T` is not a generic parameter
6565

6666
error: cross-crate traits with a default impl, like `Sync`, should not be specialized
6767
--> $DIR/suspicious-impls-lint.rs:46:1
@@ -71,12 +71,12 @@ LL | unsafe impl<T> Sync for WithLifetime<'static, Vec<T>> {}
7171
|
7272
= warning: this will change its meaning in a future release!
7373
= note: for more information, see issue #93367 <https://github.com/rust-lang/rust/issues/93367>
74+
= note: `Vec<T>` is not a generic parameter
7475
note: try using the same sequence of generic parameters as the struct definition
7576
--> $DIR/suspicious-impls-lint.rs:44:1
7677
|
7778
LL | pub struct WithLifetime<'a, T>(&'a (), T);
7879
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
79-
= note: `Vec<T>` is not a generic parameter
8080

8181
error: aborting due to 5 previous errors
8282

src/test/ui/dropck/issue-38868.stderr

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ LL | | }
88
LL | | }
99
| |_^
1010
|
11+
= note: `i32` is not a generic parameter
1112
note: use the same sequence of generic type, lifetime and const parameters as the struct definition
1213
--> $DIR/issue-38868.rs:1:1
1314
|

src/test/ui/dropck/reject-specialized-drops-8142.rs

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -32,9 +32,7 @@ impl<'al,'adds_bnd> Drop for L<'al,'adds_bnd> where 'adds_bnd:'al { // RE
3232
impl<'ml> Drop for M<'ml> { fn drop(&mut self) { } } // ACCEPT
3333

3434
impl Drop for N<'static> { fn drop(&mut self) { } } // REJECT
35-
//~^ ERROR mismatched types
36-
//~| expected struct `N<'n>`
37-
//~| found struct `N<'static>`
35+
//~^ ERROR `Drop` impls cannot be specialized
3836

3937
impl<COkNoBound> Drop for O<COkNoBound> { fn drop(&mut self) { } } // ACCEPT
4038

@@ -57,7 +55,7 @@ impl<One> Drop for V<One,One> { fn drop(&mut self) { } } // REJECT
5755
//~^ ERROR `Drop` impls cannot be specialized
5856

5957
impl<'lw> Drop for W<'lw,'lw> { fn drop(&mut self) { } } // REJECT
60-
//~^ ERROR cannot infer an appropriate lifetime for lifetime parameter `'lw`
58+
//~^ ERROR `Drop` impls cannot be specialized
6159

6260
impl Drop for X<3> { fn drop(&mut self) { } } // REJECT
6361
//~^ ERROR `Drop` impls cannot be specialized

0 commit comments

Comments
 (0)