From f3f68324cc0eddf115270a71147738eb94cbcad0 Mon Sep 17 00:00:00 2001 From: lcnr Date: Wed, 23 Mar 2022 09:41:31 +0100 Subject: [PATCH 1/5] move unique param check into `rustc_middle` --- compiler/rustc_middle/src/ty/util.rs | 119 +++++++++++++----- compiler/rustc_typeck/src/coherence/orphan.rs | 58 +-------- 2 files changed, 93 insertions(+), 84 deletions(-) diff --git a/compiler/rustc_middle/src/ty/util.rs b/compiler/rustc_middle/src/ty/util.rs index 55f08b5678aa3..bf066f65aeb12 100644 --- a/compiler/rustc_middle/src/ty/util.rs +++ b/compiler/rustc_middle/src/ty/util.rs @@ -5,10 +5,7 @@ use crate::ty::fold::{FallibleTypeFolder, TypeFolder}; use crate::ty::layout::IntegerExt; use crate::ty::query::TyCtxtAt; use crate::ty::subst::{GenericArgKind, Subst, SubstsRef}; -use crate::ty::{ - self, DebruijnIndex, DefIdTree, EarlyBinder, List, ReEarlyBound, Ty, TyCtxt, TyKind::*, - TypeFoldable, -}; +use crate::ty::{self, DefIdTree, Ty, TyCtxt, TypeFoldable}; use rustc_apfloat::Float as _; use rustc_ast as ast; use rustc_attr::{self as attr, SignedInt, UnsignedInt}; @@ -18,6 +15,7 @@ use rustc_errors::ErrorGuaranteed; use rustc_hir as hir; use rustc_hir::def::{CtorOf, DefKind, Res}; use rustc_hir::def_id::DefId; +use rustc_index::bit_set::GrowableBitSet; use rustc_macros::HashStable; use rustc_span::{sym, DUMMY_SP}; use rustc_target::abi::{Integer, Size, TargetDataLayout}; @@ -32,6 +30,12 @@ pub struct Discr<'tcx> { pub ty: Ty<'tcx>, } +#[derive(Copy, Clone, Debug)] +pub enum NotUniqueParam<'tcx> { + DuplicateParam(ty::GenericArg<'tcx>), + NotParam(ty::GenericArg<'tcx>), +} + impl<'tcx> fmt::Display for Discr<'tcx> { fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result { match *self.ty.kind() { @@ -49,8 +53,8 @@ impl<'tcx> fmt::Display for Discr<'tcx> { fn int_size_and_signed<'tcx>(tcx: TyCtxt<'tcx>, ty: Ty<'tcx>) -> (Size, bool) { let (int, signed) = match *ty.kind() { - Int(ity) => (Integer::from_int_ty(&tcx, ity), true), - Uint(uty) => (Integer::from_uint_ty(&tcx, uty), false), + ty::Int(ity) => (Integer::from_int_ty(&tcx, ity), true), + ty::Uint(uty) => (Integer::from_uint_ty(&tcx, uty), false), _ => bug!("non integer discriminant"), }; (int.size(), signed) @@ -176,7 +180,7 @@ impl<'tcx> TyCtxt<'tcx> { if let ty::Adt(def, substs) = *ty.kind() { for field in def.all_fields() { let field_ty = field.ty(self, substs); - if let Error(_) = field_ty.kind() { + if let ty::Error(_) = field_ty.kind() { return true; } } @@ -311,7 +315,7 @@ impl<'tcx> TyCtxt<'tcx> { let (mut a, mut b) = (source, target); loop { match (&a.kind(), &b.kind()) { - (&Adt(a_def, a_substs), &Adt(b_def, b_substs)) + (&ty::Adt(a_def, a_substs), &ty::Adt(b_def, b_substs)) if a_def == b_def && a_def.is_struct() => { if let Some(f) = a_def.non_enum_variant().fields.last() { @@ -321,7 +325,7 @@ impl<'tcx> TyCtxt<'tcx> { break; } } - (&Tuple(a_tys), &Tuple(b_tys)) if a_tys.len() == b_tys.len() => { + (&ty::Tuple(a_tys), &ty::Tuple(b_tys)) if a_tys.len() == b_tys.len() => { if let Some(&a_last) = a_tys.last() { a = a_last; b = *b_tys.last().unwrap(); @@ -427,7 +431,7 @@ impl<'tcx> TyCtxt<'tcx> { .filter(|&(_, k)| { match k.unpack() { GenericArgKind::Lifetime(region) => match region.kind() { - ReEarlyBound(ref ebr) => { + ty::ReEarlyBound(ref ebr) => { !impl_generics.region_param(ebr, self).pure_wrt_drop } // Error: not a region param @@ -453,6 +457,49 @@ impl<'tcx> TyCtxt<'tcx> { result } + /// Checks whether each generic argument is simply a unique generic parameter. + pub fn uses_unique_generic_params( + self, + substs: SubstsRef<'tcx>, + ignore_regions: bool, + ) -> Result<(), NotUniqueParam<'tcx>> { + let mut seen = GrowableBitSet::default(); + for arg in substs { + match arg.unpack() { + GenericArgKind::Lifetime(lt) => { + if !ignore_regions { + match lt.kind() { + ty::ReEarlyBound(p) => { + if !seen.insert(p.index) { + return Err(NotUniqueParam::DuplicateParam(lt.into())); + } + } + _ => return Err(NotUniqueParam::NotParam(lt.into())), + } + } + } + GenericArgKind::Type(t) => match t.kind() { + ty::Param(p) => { + if !seen.insert(p.index) { + return Err(NotUniqueParam::DuplicateParam(t.into())); + } + } + _ => return Err(NotUniqueParam::NotParam(t.into())), + }, + GenericArgKind::Const(c) => match c.val() { + ty::ConstKind::Param(p) => { + if !seen.insert(p.index) { + return Err(NotUniqueParam::DuplicateParam(c.into())); + } + } + _ => return Err(NotUniqueParam::NotParam(c.into())), + }, + } + } + + Ok(()) + } + /// Returns `true` if `def_id` refers to a closure (e.g., `|x| x * 2`). Note /// that closures have a `DefId`, but the closure *expression* also /// has a `HirId` that is located within the context where the @@ -594,30 +641,33 @@ impl<'tcx> TyCtxt<'tcx> { if visitor.found_recursion { Err(expanded_type) } else { Ok(expanded_type) } } - pub fn bound_type_of(self, def_id: DefId) -> EarlyBinder> { - EarlyBinder(self.type_of(def_id)) + pub fn bound_type_of(self, def_id: DefId) -> ty::EarlyBinder> { + ty::EarlyBinder(self.type_of(def_id)) } - pub fn bound_fn_sig(self, def_id: DefId) -> EarlyBinder> { - EarlyBinder(self.fn_sig(def_id)) + pub fn bound_fn_sig(self, def_id: DefId) -> ty::EarlyBinder> { + ty::EarlyBinder(self.fn_sig(def_id)) } - pub fn bound_impl_trait_ref(self, def_id: DefId) -> Option>> { - self.impl_trait_ref(def_id).map(|i| EarlyBinder(i)) + pub fn bound_impl_trait_ref( + self, + def_id: DefId, + ) -> Option>> { + self.impl_trait_ref(def_id).map(|i| ty::EarlyBinder(i)) } pub fn bound_explicit_item_bounds( self, def_id: DefId, - ) -> EarlyBinder<&'tcx [(ty::Predicate<'tcx>, rustc_span::Span)]> { - EarlyBinder(self.explicit_item_bounds(def_id)) + ) -> ty::EarlyBinder<&'tcx [(ty::Predicate<'tcx>, rustc_span::Span)]> { + ty::EarlyBinder(self.explicit_item_bounds(def_id)) } pub fn bound_item_bounds( self, def_id: DefId, - ) -> EarlyBinder<&'tcx ty::List>> { - EarlyBinder(self.item_bounds(def_id)) + ) -> ty::EarlyBinder<&'tcx ty::List>> { + ty::EarlyBinder(self.item_bounds(def_id)) } } @@ -930,35 +980,40 @@ impl<'tcx> Ty<'tcx> { pub fn is_structural_eq_shallow(self, tcx: TyCtxt<'tcx>) -> bool { match self.kind() { // Look for an impl of both `PartialStructuralEq` and `StructuralEq`. - Adt(..) => tcx.has_structural_eq_impls(self), + ty::Adt(..) => tcx.has_structural_eq_impls(self), // Primitive types that satisfy `Eq`. - Bool | Char | Int(_) | Uint(_) | Str | Never => true, + ty::Bool | ty::Char | ty::Int(_) | ty::Uint(_) | ty::Str | ty::Never => true, // Composite types that satisfy `Eq` when all of their fields do. // // Because this function is "shallow", we return `true` for these composites regardless // of the type(s) contained within. - Ref(..) | Array(..) | Slice(_) | Tuple(..) => true, + ty::Ref(..) | ty::Array(..) | ty::Slice(_) | ty::Tuple(..) => true, // Raw pointers use bitwise comparison. - RawPtr(_) | FnPtr(_) => true, + ty::RawPtr(_) | ty::FnPtr(_) => true, // Floating point numbers are not `Eq`. - Float(_) => false, + ty::Float(_) => false, // Conservatively return `false` for all others... // Anonymous function types - FnDef(..) | Closure(..) | Dynamic(..) | Generator(..) => false, + ty::FnDef(..) | ty::Closure(..) | ty::Dynamic(..) | ty::Generator(..) => false, // Generic or inferred types // // FIXME(ecstaticmorse): Maybe we should `bug` here? This should probably only be // called for known, fully-monomorphized types. - Projection(_) | Opaque(..) | Param(_) | Bound(..) | Placeholder(_) | Infer(_) => false, + ty::Projection(_) + | ty::Opaque(..) + | ty::Param(_) + | ty::Bound(..) + | ty::Placeholder(_) + | ty::Infer(_) => false, - Foreign(_) | GeneratorWitness(..) | Error(_) => false, + ty::Foreign(_) | ty::GeneratorWitness(..) | ty::Error(_) => false, } } @@ -974,13 +1029,13 @@ impl<'tcx> Ty<'tcx> { /// - `&'a *const &'b u8 -> *const &'b u8` pub fn peel_refs(self) -> Ty<'tcx> { let mut ty = self; - while let Ref(_, inner_ty, _) = ty.kind() { + while let ty::Ref(_, inner_ty, _) = ty.kind() { ty = *inner_ty; } ty } - pub fn outer_exclusive_binder(self) -> DebruijnIndex { + pub fn outer_exclusive_binder(self) -> ty::DebruijnIndex { self.0.outer_exclusive_binder } } @@ -1177,8 +1232,8 @@ pub struct AlwaysRequiresDrop; /// with their underlying types. pub fn normalize_opaque_types<'tcx>( tcx: TyCtxt<'tcx>, - val: &'tcx List>, -) -> &'tcx List> { + val: &'tcx ty::List>, +) -> &'tcx ty::List> { let mut visitor = OpaqueTypeExpander { seen_opaque_tys: FxHashSet::default(), expanded_cache: FxHashMap::default(), diff --git a/compiler/rustc_typeck/src/coherence/orphan.rs b/compiler/rustc_typeck/src/coherence/orphan.rs index f57986a985cde..ad8a84d536fed 100644 --- a/compiler/rustc_typeck/src/coherence/orphan.rs +++ b/compiler/rustc_typeck/src/coherence/orphan.rs @@ -5,10 +5,9 @@ use rustc_data_structures::fx::FxHashSet; use rustc_errors::struct_span_err; use rustc_errors::ErrorGuaranteed; use rustc_hir as hir; -use rustc_index::bit_set::GrowableBitSet; use rustc_infer::infer::TyCtxtInferExt; use rustc_middle::ty::subst::GenericArgKind; -use rustc_middle::ty::subst::{GenericArg, InternalSubsts}; +use rustc_middle::ty::subst::InternalSubsts; use rustc_middle::ty::{self, ImplPolarity, Ty, TyCtxt, TypeFoldable, TypeVisitor}; use rustc_session::lint; use rustc_span::def_id::{DefId, LocalDefId}; @@ -325,51 +324,6 @@ fn emit_orphan_check_error<'tcx>( }) } -#[derive(Default)] -struct AreUniqueParamsVisitor { - seen: GrowableBitSet, -} - -#[derive(Copy, Clone)] -enum NotUniqueParam<'tcx> { - DuplicateParam(GenericArg<'tcx>), - NotParam(GenericArg<'tcx>), -} - -impl<'tcx> TypeVisitor<'tcx> for AreUniqueParamsVisitor { - type BreakTy = NotUniqueParam<'tcx>; - fn visit_ty(&mut self, t: Ty<'tcx>) -> ControlFlow { - match t.kind() { - ty::Param(p) => { - if self.seen.insert(p.index) { - ControlFlow::CONTINUE - } else { - ControlFlow::Break(NotUniqueParam::DuplicateParam(t.into())) - } - } - _ => ControlFlow::Break(NotUniqueParam::NotParam(t.into())), - } - } - fn visit_region(&mut self, _: ty::Region<'tcx>) -> ControlFlow { - // We don't drop candidates during candidate assembly because of region - // constraints, so the behavior for impls only constrained by regions - // will not change. - ControlFlow::CONTINUE - } - fn visit_const(&mut self, c: ty::Const<'tcx>) -> ControlFlow { - match c.val() { - ty::ConstKind::Param(p) => { - if self.seen.insert(p.index) { - ControlFlow::CONTINUE - } else { - ControlFlow::Break(NotUniqueParam::DuplicateParam(c.into())) - } - } - _ => ControlFlow::Break(NotUniqueParam::NotParam(c.into())), - } - } -} - /// Lint impls of auto traits if they are likely to have /// unsound or surprising effects on auto impls. fn lint_auto_trait_impls(tcx: TyCtxt<'_>, trait_def_id: DefId, impls: &[LocalDefId]) { @@ -400,9 +354,9 @@ fn lint_auto_trait_impls(tcx: TyCtxt<'_>, trait_def_id: DefId, impls: &[LocalDef // Impls which completely cover a given root type are fine as they // disable auto impls entirely. So only lint if the substs // are not a permutation of the identity substs. - match substs.visit_with(&mut AreUniqueParamsVisitor::default()) { - ControlFlow::Continue(()) => {} // ok - ControlFlow::Break(arg) => { + match tcx.uses_unique_generic_params(substs, true) { + Ok(()) => {} // ok + Err(arg) => { // Ideally: // // - compute the requirements for the auto impl candidate @@ -444,10 +398,10 @@ fn lint_auto_trait_impls(tcx: TyCtxt<'_>, trait_def_id: DefId, impls: &[LocalDef ), ); match arg { - NotUniqueParam::DuplicateParam(arg) => { + ty::util::NotUniqueParam::DuplicateParam(arg) => { err.note(&format!("`{}` is mentioned multiple times", arg)); } - NotUniqueParam::NotParam(arg) => { + ty::util::NotUniqueParam::NotParam(arg) => { err.note(&format!("`{}` is not a generic parameter", arg)); } } From 5ac973426eb1f6b3dd9b883daedbfe71f27da704 Mon Sep 17 00:00:00 2001 From: lcnr Date: Wed, 23 Mar 2022 10:06:29 +0100 Subject: [PATCH 2/5] rewrite `ensure_drop_params_and_item_params_correspond` --- compiler/rustc_typeck/src/check/dropck.rs | 101 +++++------------- 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, 72 insertions(+), 127 deletions(-) diff --git a/compiler/rustc_typeck/src/check/dropck.rs b/compiler/rustc_typeck/src/check/dropck.rs index 9caa4a40df71f..0b0f7a085fcba 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); - - // 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 Err(arg) = tcx.uses_unique_generic_params(drop_impl_substs, false) else { + return Ok(()) + }; + + 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 ad8a84d536fed..f8b3f1ac3df32 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 e299e5369fe03..03460b28dcd5a 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 10d1e7c4e66dc..f369b74cf5515 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 c9599f6e805bb..7a3bbe7cb0932 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 8dbde9d417df0..82e95ea075dec 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 - | -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 + = 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: ...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`. From 4fcf43f67cd5be83bbb72a1cbf76bdfc95d7c83b Mon Sep 17 00:00:00 2001 From: lcnr Date: Fri, 25 Mar 2022 14:49:14 +0100 Subject: [PATCH 3/5] update comments --- compiler/rustc_infer/src/infer/mod.rs | 2 +- compiler/rustc_infer/src/infer/outlives/obligations.rs | 8 +------- 2 files changed, 2 insertions(+), 8 deletions(-) diff --git a/compiler/rustc_infer/src/infer/mod.rs b/compiler/rustc_infer/src/infer/mod.rs index c9121f7d348ce..4ef6f240c4808 100644 --- a/compiler/rustc_infer/src/infer/mod.rs +++ b/compiler/rustc_infer/src/infer/mod.rs @@ -181,7 +181,7 @@ pub struct InferCtxtInner<'tcx> { /// /// Before running `resolve_regions_and_report_errors`, the creator /// of the inference context is expected to invoke - /// `process_region_obligations` (defined in `self::region_obligations`) + /// [`InferCtxt::process_registered_region_obligations`] /// for each body-id in this map, which will process the /// obligations within. This is expected to be done 'late enough' /// that all type inference variables have been bound and so forth. diff --git a/compiler/rustc_infer/src/infer/outlives/obligations.rs b/compiler/rustc_infer/src/infer/outlives/obligations.rs index 19d03ffa6964a..2aa535da0e54c 100644 --- a/compiler/rustc_infer/src/infer/outlives/obligations.rs +++ b/compiler/rustc_infer/src/infer/outlives/obligations.rs @@ -136,7 +136,7 @@ impl<'cx, 'tcx> InferCtxt<'cx, 'tcx> { /// /// # Parameters /// - /// - `region_bound_pairs`: the set of region bounds implied by + /// - `region_bound_pairs_map`: the set of region bounds implied by /// the parameters and where-clauses. In particular, each pair /// `('a, K)` in this list tells us that the bounds in scope /// indicate that `K: 'a`, where `K` is either a generic @@ -147,12 +147,6 @@ impl<'cx, 'tcx> InferCtxt<'cx, 'tcx> { /// - `param_env` is the parameter environment for the enclosing function. /// - `body_id` is the body-id whose region obligations are being /// processed. - /// - /// # Returns - /// - /// This function may have to perform normalizations, and hence it - /// returns an `InferOk` with subobligations that must be - /// processed. #[instrument(level = "debug", skip(self, region_bound_pairs_map))] pub fn process_registered_region_obligations( &self, From ced65022dae81b46e629262d8458cc3e5ac8cec1 Mon Sep 17 00:00:00 2001 From: lcnr Date: Tue, 29 Mar 2022 07:29:59 +0200 Subject: [PATCH 4/5] update error message --- compiler/rustc_typeck/src/check/dropck.rs | 2 +- src/test/ui/dropck/issue-38868.stderr | 2 +- .../ui/dropck/reject-specialized-drops-8142.stderr | 12 ++++++------ 3 files changed, 8 insertions(+), 8 deletions(-) diff --git a/compiler/rustc_typeck/src/check/dropck.rs b/compiler/rustc_typeck/src/check/dropck.rs index 0b0f7a085fcba..41b895f3bbf1f 100644 --- a/compiler/rustc_typeck/src/check/dropck.rs +++ b/compiler/rustc_typeck/src/check/dropck.rs @@ -86,7 +86,7 @@ fn ensure_drop_params_and_item_params_correspond<'tcx>( err.span_note( item_span, &format!( - "use the same sequence of generic type, lifetime and const parameters \ + "use the same sequence of generic lifetime, type and const parameters \ as the {self_descr} definition", ), ); diff --git a/src/test/ui/dropck/issue-38868.stderr b/src/test/ui/dropck/issue-38868.stderr index f369b74cf5515..f267abc0bfa79 100644 --- a/src/test/ui/dropck/issue-38868.stderr +++ b/src/test/ui/dropck/issue-38868.stderr @@ -9,7 +9,7 @@ LL | | } | |_^ | = note: `i32` is not a generic parameter -note: use the same sequence of generic type, lifetime and const parameters as the struct definition +note: use the same sequence of generic lifetime, type and const parameters as the struct definition --> $DIR/issue-38868.rs:1:1 | LL | / pub struct List { diff --git a/src/test/ui/dropck/reject-specialized-drops-8142.stderr b/src/test/ui/dropck/reject-specialized-drops-8142.stderr index 82e95ea075dec..7f50cf5ab15d2 100644 --- a/src/test/ui/dropck/reject-specialized-drops-8142.stderr +++ b/src/test/ui/dropck/reject-specialized-drops-8142.stderr @@ -29,7 +29,7 @@ LL | impl Drop for N<'static> { fn drop(&mut self) { } } | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | = note: `'static` is not a generic parameter -note: use the same sequence of generic type, lifetime and const parameters as the struct definition +note: use the same sequence of generic lifetime, type and const parameters as the struct definition --> $DIR/reject-specialized-drops-8142.rs:7:1 | LL | struct N<'n> { x: &'n i8 } @@ -42,7 +42,7 @@ LL | impl Drop for P { fn drop(&mut self) { } } // REJ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | = note: `i8` is not a generic parameter -note: use the same sequence of generic type, lifetime and const parameters as the struct definition +note: use the same sequence of generic lifetime, type and const parameters as the struct definition --> $DIR/reject-specialized-drops-8142.rs:9:1 | LL | struct P { x: *const Tp } @@ -79,7 +79,7 @@ LL | impl Drop for V { fn drop(&mut self) { } } // REJ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | = note: `One` is mentioned multiple times -note: use the same sequence of generic type, lifetime and const parameters as the struct definition +note: use the same sequence of generic lifetime, type and const parameters as the struct definition --> $DIR/reject-specialized-drops-8142.rs:15:1 | LL | struct V { x: *const Tva, y: *const Tvb } @@ -92,7 +92,7 @@ LL | impl<'lw> Drop for W<'lw,'lw> { fn drop(&mut self) { } } // REJ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | = note: `'lw` is mentioned multiple times -note: use the same sequence of generic type, lifetime and const parameters as the struct definition +note: use the same sequence of generic lifetime, type 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 } @@ -105,7 +105,7 @@ LL | impl Drop for X<3> { fn drop(&mut self) { } } // REJ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | = note: `3_usize` is not a generic parameter -note: use the same sequence of generic type, lifetime and const parameters as the struct definition +note: use the same sequence of generic lifetime, type and const parameters as the struct definition --> $DIR/reject-specialized-drops-8142.rs:17:1 | LL | struct X; @@ -118,7 +118,7 @@ LL | impl Drop for Y { fn drop(&mut self) { } } // | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | = note: `Ca` is mentioned multiple times -note: use the same sequence of generic type, lifetime and const parameters as the struct definition +note: use the same sequence of generic lifetime, type and const parameters as the struct definition --> $DIR/reject-specialized-drops-8142.rs:18:1 | LL | struct Y; From 4a82bc9ea058a3f64e0ffb9f08ce3302a60a0990 Mon Sep 17 00:00:00 2001 From: lcnr Date: Mon, 4 Apr 2022 10:56:59 +0200 Subject: [PATCH 5/5] `bool` to custom enum --- compiler/rustc_middle/src/ty/util.rs | 23 +++++++++++-------- compiler/rustc_typeck/src/check/dropck.rs | 3 ++- compiler/rustc_typeck/src/coherence/orphan.rs | 3 ++- 3 files changed, 18 insertions(+), 11 deletions(-) diff --git a/compiler/rustc_middle/src/ty/util.rs b/compiler/rustc_middle/src/ty/util.rs index bf066f65aeb12..809e7ce2e745b 100644 --- a/compiler/rustc_middle/src/ty/util.rs +++ b/compiler/rustc_middle/src/ty/util.rs @@ -30,6 +30,13 @@ pub struct Discr<'tcx> { pub ty: Ty<'tcx>, } +/// Used as an input to [`TyCtxt::uses_unique_generic_params`]. +#[derive(Copy, Clone, Debug, PartialEq, Eq)] +pub enum IgnoreRegions { + Yes, + No, +} + #[derive(Copy, Clone, Debug)] pub enum NotUniqueParam<'tcx> { DuplicateParam(ty::GenericArg<'tcx>), @@ -461,20 +468,18 @@ impl<'tcx> TyCtxt<'tcx> { pub fn uses_unique_generic_params( self, substs: SubstsRef<'tcx>, - ignore_regions: bool, + ignore_regions: IgnoreRegions, ) -> Result<(), NotUniqueParam<'tcx>> { let mut seen = GrowableBitSet::default(); for arg in substs { match arg.unpack() { GenericArgKind::Lifetime(lt) => { - if !ignore_regions { - match lt.kind() { - ty::ReEarlyBound(p) => { - if !seen.insert(p.index) { - return Err(NotUniqueParam::DuplicateParam(lt.into())); - } - } - _ => return Err(NotUniqueParam::NotParam(lt.into())), + if ignore_regions == IgnoreRegions::No { + let ty::ReEarlyBound(p) = lt.kind() else { + return Err(NotUniqueParam::NotParam(lt.into())) + }; + if !seen.insert(p.index) { + return Err(NotUniqueParam::DuplicateParam(lt.into())); } } } diff --git a/compiler/rustc_typeck/src/check/dropck.rs b/compiler/rustc_typeck/src/check/dropck.rs index 41b895f3bbf1f..f8853014d2fd4 100644 --- a/compiler/rustc_typeck/src/check/dropck.rs +++ b/compiler/rustc_typeck/src/check/dropck.rs @@ -5,6 +5,7 @@ use rustc_errors::{struct_span_err, ErrorGuaranteed}; use rustc_middle::ty::error::TypeError; use rustc_middle::ty::relate::{Relate, RelateResult, TypeRelation}; use rustc_middle::ty::subst::SubstsRef; +use rustc_middle::ty::util::IgnoreRegions; use rustc_middle::ty::{self, Predicate, Ty, TyCtxt}; use rustc_span::Span; use rustc_trait_selection::traits::query::dropck_outlives::AtExt; @@ -66,7 +67,7 @@ fn ensure_drop_params_and_item_params_correspond<'tcx>( self_type_did: DefId, drop_impl_substs: SubstsRef<'tcx>, ) -> Result<(), ErrorGuaranteed> { - let Err(arg) = tcx.uses_unique_generic_params(drop_impl_substs, false) else { + let Err(arg) = tcx.uses_unique_generic_params(drop_impl_substs, IgnoreRegions::No) else { return Ok(()) }; diff --git a/compiler/rustc_typeck/src/coherence/orphan.rs b/compiler/rustc_typeck/src/coherence/orphan.rs index f8b3f1ac3df32..eb6217f117496 100644 --- a/compiler/rustc_typeck/src/coherence/orphan.rs +++ b/compiler/rustc_typeck/src/coherence/orphan.rs @@ -8,6 +8,7 @@ use rustc_hir as hir; use rustc_infer::infer::TyCtxtInferExt; use rustc_middle::ty::subst::GenericArgKind; use rustc_middle::ty::subst::InternalSubsts; +use rustc_middle::ty::util::IgnoreRegions; use rustc_middle::ty::{self, ImplPolarity, Ty, TyCtxt, TypeFoldable, TypeVisitor}; use rustc_session::lint; use rustc_span::def_id::{DefId, LocalDefId}; @@ -354,7 +355,7 @@ fn lint_auto_trait_impls(tcx: TyCtxt<'_>, trait_def_id: DefId, impls: &[LocalDef // Impls which completely cover a given root type are fine as they // disable auto impls entirely. So only lint if the substs // are not a permutation of the identity substs. - match tcx.uses_unique_generic_params(substs, true) { + match tcx.uses_unique_generic_params(substs, IgnoreRegions::Yes) { Ok(()) => {} // ok Err(arg) => { // Ideally: