@@ -18,26 +18,29 @@ use rustc_span::Span;
1818use rustc_trait_selection::traits;
1919use std::ops::ControlFlow;
2020
21- pub(super) fn orphan_check_crate (tcx: TyCtxt<'_>, (): ()) -> &[LocalDefId] {
22- let mut errors = Vec::new();
23- for (&trait_def_id, impls_of_trait) in tcx.all_local_trait_impls(()) {
24- for &impl_of_trait in impls_of_trait {
25- match orphan_check_impl(tcx, impl_of_trait) {
26- Ok(()) => {}
27- Err(_ ) => errors.push(impl_of_trait),
28- }
29- }
21+ #[instrument(skip (tcx), level = "debug")]
22+ pub(crate) fn orphan_check_impl(
23+ tcx: TyCtxt<'_>,
24+ impl_def_id: LocalDefId,
25+ ) -> Result<(), ErrorGuaranteed> {
26+ let trait_ref = tcx.impl_trait_ref(impl_def_id).unwrap();
27+ if let Some(err ) = trait_ref.error_reported() {
28+ return Err(err);
29+ }
3030
31- if tcx.trait_is_auto(trait_def_id) {
32- lint_auto_trait_impls( tcx, trait_def_id, impls_of_trait);
33- }
31+ let ret = do_orphan_check_impl(tcx, trait_ref, impl_def_id);
32+ if tcx.trait_is_auto(trait_ref.def_id) {
33+ lint_auto_trait_impl(tcx, trait_ref, impl_def_id);
3434 }
35- tcx.arena.alloc_slice(&errors)
35+
36+ ret
3637}
3738
38- #[instrument(skip(tcx), level = "debug")]
39- fn orphan_check_impl(tcx: TyCtxt<'_>, def_id: LocalDefId) -> Result<(), ErrorGuaranteed> {
40- let trait_ref = tcx.impl_trait_ref(def_id).unwrap();
39+ fn do_orphan_check_impl<'tcx>(
40+ tcx: TyCtxt<'tcx>,
41+ trait_ref: ty::TraitRef<'tcx>,
42+ def_id: LocalDefId,
43+ ) -> Result<(), ErrorGuaranteed> {
4144 let trait_def_id = trait_ref.def_id;
4245
4346 let item = tcx.hir().item(hir::ItemId { def_id });
@@ -329,89 +332,82 @@ fn emit_orphan_check_error<'tcx>(
329332
330333/// Lint impls of auto traits if they are likely to have
331334/// unsound or surprising effects on auto impls.
332- fn lint_auto_trait_impls(tcx: TyCtxt<'_>, trait_def_id: DefId, impls: &[LocalDefId]) {
333- let mut non_covering_impls = Vec::new();
334- for &impl_def_id in impls {
335- let trait_ref = tcx.impl_trait_ref(impl_def_id).unwrap();
336- if trait_ref.references_error() {
337- return;
338- }
335+ fn lint_auto_trait_impl<'tcx>(
336+ tcx: TyCtxt<'tcx>,
337+ trait_ref: ty::TraitRef<'tcx>,
338+ impl_def_id: LocalDefId,
339+ ) {
340+ if tcx.impl_polarity(impl_def_id) != ImplPolarity::Positive {
341+ return;
342+ }
339343
340- if tcx.impl_polarity(impl_def_id) != ImplPolarity::Positive {
344+ assert_eq!(trait_ref.substs.len(), 1);
345+ let self_ty = trait_ref.self_ty();
346+ let (self_type_did, substs) = match self_ty.kind() {
347+ ty::Adt(def, substs) => (def.did(), substs),
348+ _ => {
349+ // FIXME: should also lint for stuff like `&i32` but
350+ // considering that auto traits are unstable, that
351+ // isn't too important for now as this only affects
352+ // crates using `nightly`, and std.
341353 return;
342354 }
355+ };
343356
344- assert_eq!(trait_ref.substs.len(), 1);
345- let self_ty = trait_ref.self_ty();
346- let (self_type_did, substs) = match self_ty.kind() {
347- ty::Adt(def, substs) => (def.did(), substs),
348- _ => {
349- // FIXME: should also lint for stuff like `&i32` but
350- // considering that auto traits are unstable, that
351- // isn't too important for now as this only affects
352- // crates using `nightly`, and std.
353- continue;
354- }
355- };
357+ // Impls which completely cover a given root type are fine as they
358+ // disable auto impls entirely. So only lint if the substs
359+ // are not a permutation of the identity substs.
360+ let Err(arg) = tcx.uses_unique_generic_params(substs, IgnoreRegions::Yes) else {
361+ // ok
362+ return;
363+ };
356364
357- // Impls which completely cover a given root type are fine as they
358- // disable auto impls entirely. So only lint if the substs
359- // are not a permutation of the identity substs.
360- match tcx.uses_unique_generic_params(substs, IgnoreRegions::Yes) {
361- Ok(()) => {} // ok
362- Err(arg) => {
363- // Ideally:
364- //
365- // - compute the requirements for the auto impl candidate
366- // - check whether these are implied by the non covering impls
367- // - if not, emit the lint
368- //
369- // What we do here is a bit simpler:
370- //
371- // - badly check if an auto impl candidate definitely does not apply
372- // for the given simplified type
373- // - if so, do not lint
374- if fast_reject_auto_impl(tcx, trait_def_id, self_ty) {
375- // ok
376- } else {
377- non_covering_impls.push((impl_def_id, self_type_did, arg));
378- }
379- }
380- }
365+ // Ideally:
366+ //
367+ // - compute the requirements for the auto impl candidate
368+ // - check whether these are implied by the non covering impls
369+ // - if not, emit the lint
370+ //
371+ // What we do here is a bit simpler:
372+ //
373+ // - badly check if an auto impl candidate definitely does not apply
374+ // for the given simplified type
375+ // - if so, do not lint
376+ if fast_reject_auto_impl(tcx, trait_ref.def_id, self_ty) {
377+ // ok
378+ return;
381379 }
382380
383- for &(impl_def_id, self_type_did, arg) in &non_covering_impls {
384- tcx.struct_span_lint_hir(
385- lint::builtin::SUSPICIOUS_AUTO_TRAIT_IMPLS,
386- tcx.hir().local_def_id_to_hir_id(impl_def_id),
387- tcx.def_span(impl_def_id),
388- |err| {
389- let item_span = tcx.def_span(self_type_did);
390- let self_descr = tcx.def_kind(self_type_did).descr(self_type_did);
391- let mut err = err.build(&format!(
392- "cross-crate traits with a default impl, like `{}`, \
381+ tcx.struct_span_lint_hir(
382+ lint::builtin::SUSPICIOUS_AUTO_TRAIT_IMPLS,
383+ tcx.hir().local_def_id_to_hir_id(impl_def_id),
384+ tcx.def_span(impl_def_id),
385+ |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);
388+ let mut err = err.build(&format!(
389+ "cross-crate traits with a default impl, like `{}`, \
393390 should not be specialized",
394- tcx.def_path_str(trait_def_id),
395- ));
396- match arg {
397- ty::util::NotUniqueParam::DuplicateParam(arg) => {
398- err.note(&format!("`{}` is mentioned multiple times", arg));
399- }
400- ty::util::NotUniqueParam::NotParam(arg) => {
401- err.note(&format!("`{}` is not a generic parameter", arg));
402- }
391+ tcx.def_path_str(trait_ref.def_id),
392+ ));
393+ match arg {
394+ ty::util::NotUniqueParam::DuplicateParam(arg) => {
395+ err.note(&format!("`{}` is mentioned multiple times", arg));
403396 }
404- err.span_note(
405- item_span,
406- &format!(
407- "try using the same sequence of generic parameters as the {} definition",
408- self_descr,
409- ),
410- );
411- err.emit();
412- },
413- );
414- }
397+ ty::util::NotUniqueParam::NotParam(arg) => {
398+ err.note(&format!("`{}` is not a generic parameter", arg));
399+ }
400+ }
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+ );
408+ err.emit();
409+ },
410+ );
415411}
416412
417413fn fast_reject_auto_impl<'tcx>(tcx: TyCtxt<'tcx>, trait_def_id: DefId, self_ty: Ty<'tcx>) -> bool {
0 commit comments