diff options
Diffstat (limited to 'compiler/rustc_hir_analysis/src')
20 files changed, 451 insertions, 121 deletions
diff --git a/compiler/rustc_hir_analysis/src/astconv/bounds.rs b/compiler/rustc_hir_analysis/src/astconv/bounds.rs index 1ae267d1a40..7157382c883 100644 --- a/compiler/rustc_hir_analysis/src/astconv/bounds.rs +++ b/compiler/rustc_hir_analysis/src/astconv/bounds.rs @@ -336,12 +336,12 @@ impl<'tcx> dyn AstConv<'tcx> + '_ { let projection_ty = if let ty::AssocKind::Fn = assoc_kind { let mut emitted_bad_param_err = None; - // If we have an method return type bound, then we need to substitute + // If we have an method return type bound, then we need to instantiate // the method's early bound params with suitable late-bound params. let mut num_bound_vars = candidate.bound_vars().len(); let args = candidate.skip_binder().args.extend_to(tcx, assoc_item.def_id, |param, _| { - let subst = match param.kind { + let arg = match param.kind { ty::GenericParamDefKind::Lifetime => ty::Region::new_bound( tcx, ty::INNERMOST, @@ -379,7 +379,7 @@ impl<'tcx> dyn AstConv<'tcx> + '_ { } }; num_bound_vars += 1; - subst + arg }); // Next, we need to check that the return-type notation is being used on @@ -402,12 +402,13 @@ impl<'tcx> dyn AstConv<'tcx> + '_ { // Finally, move the fn return type's bound vars over to account for the early bound // params (and trait ref's late bound params). This logic is very similar to - // `Predicate::subst_supertrait`, and it's no coincidence why. + // `rustc_middle::ty::predicate::Clause::instantiate_supertrait` + // and it's no coincidence why. let shifted_output = tcx.shift_bound_var_indices(num_bound_vars, output); - let subst_output = ty::EarlyBinder::bind(shifted_output).instantiate(tcx, args); + let instantiation_output = ty::EarlyBinder::bind(shifted_output).instantiate(tcx, args); let bound_vars = tcx.late_bound_vars(binding.hir_id); - ty::Binder::bind_with_vars(subst_output, bound_vars) + ty::Binder::bind_with_vars(instantiation_output, bound_vars) } else { // Append the generic arguments of the associated type to the `trait_ref`. candidate.map_bound(|trait_ref| { diff --git a/compiler/rustc_hir_analysis/src/astconv/generics.rs b/compiler/rustc_hir_analysis/src/astconv/generics.rs index aa826c1f268..614e5f9d32b 100644 --- a/compiler/rustc_hir_analysis/src/astconv/generics.rs +++ b/compiler/rustc_hir_analysis/src/astconv/generics.rs @@ -1,6 +1,6 @@ use super::IsMethodCall; use crate::astconv::{ - errors::prohibit_assoc_ty_binding, CreateSubstsForGenericArgsCtxt, ExplicitLateBound, + errors::prohibit_assoc_ty_binding, CreateInstantiationsForGenericArgsCtxt, ExplicitLateBound, GenericArgCountMismatch, GenericArgCountResult, GenericArgPosition, }; use crate::structured_errors::{GenericArgsInfo, StructuredDiagnostic, WrongNumberOfGenericArgs}; @@ -177,9 +177,9 @@ pub fn create_args_for_parent_generic_args<'tcx: 'a, 'a>( has_self: bool, self_ty: Option<Ty<'tcx>>, arg_count: &GenericArgCountResult, - ctx: &mut impl CreateSubstsForGenericArgsCtxt<'a, 'tcx>, + ctx: &mut impl CreateInstantiationsForGenericArgsCtxt<'a, 'tcx>, ) -> GenericArgsRef<'tcx> { - // Collect the segments of the path; we need to substitute arguments + // Collect the segments of the path; we need to instantiate arguments // for parameters throughout the entire path (wherever there are // generic parameters). let mut parent_defs = tcx.generics_of(def_id); @@ -191,7 +191,7 @@ pub fn create_args_for_parent_generic_args<'tcx: 'a, 'a>( } // We manually build up the generic arguments, rather than using convenience - // methods in `subst.rs`, so that we can iterate over the arguments and + // methods in `rustc_middle/src/ty/generic_args.rs`, so that we can iterate over the arguments and // parameters in lock-step linearly, instead of trying to match each pair. let mut args: SmallVec<[ty::GenericArg<'tcx>; 8]> = SmallVec::with_capacity(count); // Iterate over each segment of the path. diff --git a/compiler/rustc_hir_analysis/src/astconv/mod.rs b/compiler/rustc_hir_analysis/src/astconv/mod.rs index 1ae3ebaebbb..cc1ccff1a1d 100644 --- a/compiler/rustc_hir_analysis/src/astconv/mod.rs +++ b/compiler/rustc_hir_analysis/src/astconv/mod.rs @@ -214,7 +214,7 @@ pub struct GenericArgCountResult { pub correct: Result<(), GenericArgCountMismatch>, } -pub trait CreateSubstsForGenericArgsCtxt<'a, 'tcx> { +pub trait CreateInstantiationsForGenericArgsCtxt<'a, 'tcx> { fn args_for_def_id(&mut self, def_id: DefId) -> (Option<&'a GenericArgs<'tcx>>, bool); fn provided_kind( @@ -366,8 +366,8 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { if generics.has_self { if generics.parent.is_some() { - // The parent is a trait so it should have at least one subst - // for the `Self` type. + // The parent is a trait so it should have at least one + // generic parameter for the `Self` type. assert!(!parent_args.is_empty()) } else { // This item (presumably a trait) needs a self-type. @@ -402,7 +402,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { return (tcx.mk_args(parent_args), arg_count); } - struct SubstsForAstPathCtxt<'a, 'tcx> { + struct InstantiationsForAstPathCtxt<'a, 'tcx> { astconv: &'a (dyn AstConv<'tcx> + 'a), def_id: DefId, generic_args: &'a GenericArgs<'tcx>, @@ -411,7 +411,9 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { infer_args: bool, } - impl<'a, 'tcx> CreateSubstsForGenericArgsCtxt<'a, 'tcx> for SubstsForAstPathCtxt<'a, 'tcx> { + impl<'a, 'tcx> CreateInstantiationsForGenericArgsCtxt<'a, 'tcx> + for InstantiationsForAstPathCtxt<'a, 'tcx> + { fn args_for_def_id(&mut self, did: DefId) -> (Option<&'a GenericArgs<'tcx>>, bool) { if did == self.def_id { (Some(self.generic_args), self.infer_args) @@ -556,7 +558,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { } } - let mut args_ctx = SubstsForAstPathCtxt { + let mut args_ctx = InstantiationsForAstPathCtxt { astconv: self, def_id, span, @@ -2412,8 +2414,8 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { let self_ty = self.tcx().type_of(parent).instantiate_identity(); let generic_self_ty = ty::GenericArg::from(self_ty); - let substs = self.tcx().mk_args_from_iter(std::iter::once(generic_self_ty)); - sig.instantiate(self.tcx(), substs) + let args = self.tcx().mk_args_from_iter(std::iter::once(generic_self_ty)); + sig.instantiate(self.tcx(), args) } else { sig.instantiate_identity() }; @@ -2457,6 +2459,19 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { hir::TyKind::Tup(fields) => { Ty::new_tup_from_iter(tcx, fields.iter().map(|t| self.ast_ty_to_ty(t))) } + hir::TyKind::AnonAdt(item_id) => { + let did = item_id.owner_id.def_id; + let adt_def = tcx.adt_def(did); + let generics = tcx.generics_of(did); + + debug!("ast_ty_to_ty_inner(AnonAdt): generics={:?}", generics); + let args = ty::GenericArgs::for_item(tcx, did.to_def_id(), |param, _| { + tcx.mk_param_from_def(param) + }); + debug!("ast_ty_to_ty_inner(AnonAdt): args={:?}", args); + + Ty::new_adt(tcx, adt_def, tcx.mk_args(args)) + } hir::TyKind::BareFn(bf) => { require_c_abi_if_c_variadic(tcx, bf.decl, bf.abi, ast_ty.span); diff --git a/compiler/rustc_hir_analysis/src/astconv/object_safety.rs b/compiler/rustc_hir_analysis/src/astconv/object_safety.rs index 2d85ad5789e..cbbf560076e 100644 --- a/compiler/rustc_hir_analysis/src/astconv/object_safety.rs +++ b/compiler/rustc_hir_analysis/src/astconv/object_safety.rs @@ -175,7 +175,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { } ty::PredicateKind::Clause(ty::ClauseKind::Projection(pred)) => { let pred = bound_predicate.rebind(pred); - // A `Self` within the original bound will be substituted with a + // A `Self` within the original bound will be instantiated with a // `trait_object_dummy_self`, so check for that. let references_self = match pred.skip_binder().term.unpack() { ty::TermKind::Ty(ty) => ty.walk().any(|arg| arg == dummy_self.into()), diff --git a/compiler/rustc_hir_analysis/src/autoderef.rs b/compiler/rustc_hir_analysis/src/autoderef.rs index 5bc904e5930..f2ceb470264 100644 --- a/compiler/rustc_hir_analysis/src/autoderef.rs +++ b/compiler/rustc_hir_analysis/src/autoderef.rs @@ -91,10 +91,6 @@ impl<'a, 'tcx> Iterator for Autoderef<'a, 'tcx> { return None; }; - if new_ty.references_error() { - return None; - } - self.state.steps.push((self.state.cur_ty, kind)); debug!( "autoderef stage #{:?} is {:?} from {:?}", @@ -137,6 +133,10 @@ impl<'a, 'tcx> Autoderef<'a, 'tcx> { debug!("overloaded_deref_ty({:?})", ty); let tcx = self.infcx.tcx; + if ty.references_error() { + return None; + } + // <ty as Deref> let trait_ref = ty::TraitRef::new(tcx, tcx.lang_items().deref_trait()?, [ty]); let cause = traits::ObligationCause::misc(self.span, self.body_id); diff --git a/compiler/rustc_hir_analysis/src/check/check.rs b/compiler/rustc_hir_analysis/src/check/check.rs index 7250dc81faf..88800491ba2 100644 --- a/compiler/rustc_hir_analysis/src/check/check.rs +++ b/compiler/rustc_hir_analysis/src/check/check.rs @@ -80,6 +80,7 @@ fn check_struct(tcx: TyCtxt<'_>, def_id: LocalDefId) { check_transparent(tcx, def); check_packed(tcx, span, def); + check_unnamed_fields(tcx, def); } fn check_union(tcx: TyCtxt<'_>, def_id: LocalDefId) { @@ -89,6 +90,58 @@ fn check_union(tcx: TyCtxt<'_>, def_id: LocalDefId) { check_transparent(tcx, def); check_union_fields(tcx, span, def_id); check_packed(tcx, span, def); + check_unnamed_fields(tcx, def); +} + +/// Check the representation of adts with unnamed fields. +fn check_unnamed_fields(tcx: TyCtxt<'_>, def: ty::AdtDef<'_>) { + if def.is_enum() { + return; + } + let variant = def.non_enum_variant(); + if !variant.has_unnamed_fields() { + return; + } + if !def.is_anonymous() { + let adt_kind = def.descr(); + let span = tcx.def_span(def.did()); + let unnamed_fields = variant + .fields + .iter() + .filter(|f| f.is_unnamed()) + .map(|f| { + let span = tcx.def_span(f.did); + errors::UnnamedFieldsReprFieldDefined { span } + }) + .collect::<Vec<_>>(); + debug_assert_ne!(unnamed_fields.len(), 0, "expect unnamed fields in this adt"); + let adt_name = tcx.item_name(def.did()); + if !def.repr().c() { + tcx.dcx().emit_err(errors::UnnamedFieldsRepr::MissingReprC { + span, + adt_kind, + adt_name, + unnamed_fields, + sugg_span: span.shrink_to_lo(), + }); + } + } + for field in variant.fields.iter().filter(|f| f.is_unnamed()) { + let field_ty = tcx.type_of(field.did).instantiate_identity(); + if let Some(adt) = field_ty.ty_adt_def() + && !adt.is_anonymous() + && !adt.repr().c() + { + let field_ty_span = tcx.def_span(adt.did()); + tcx.dcx().emit_err(errors::UnnamedFieldsRepr::FieldMissingReprC { + span: tcx.def_span(field.did), + field_ty_span, + field_ty, + field_adt_kind: adt.descr(), + sugg_span: field_ty_span.shrink_to_lo(), + }); + } + } } /// Check that the fields of the `union` do not need dropping. @@ -1030,7 +1083,7 @@ pub(super) fn check_transparent<'tcx>(tcx: TyCtxt<'tcx>, adt: ty::AdtDef<'tcx>) match t.kind() { ty::Tuple(list) => list.iter().try_for_each(|t| check_non_exhaustive(tcx, t)), ty::Array(ty, _) => check_non_exhaustive(tcx, *ty), - ty::Adt(def, subst) => { + ty::Adt(def, args) => { if !def.did().is_local() { let non_exhaustive = def.is_variant_list_non_exhaustive() || def @@ -1042,13 +1095,13 @@ pub(super) fn check_transparent<'tcx>(tcx: TyCtxt<'tcx>, adt: ty::AdtDef<'tcx>) return ControlFlow::Break(( def.descr(), def.did(), - subst, + args, non_exhaustive, )); } } def.all_fields() - .map(|field| field.ty(tcx, subst)) + .map(|field| field.ty(tcx, args)) .try_for_each(|t| check_non_exhaustive(tcx, t)) } _ => ControlFlow::Continue(()), diff --git a/compiler/rustc_hir_analysis/src/check/compare_impl_item.rs b/compiler/rustc_hir_analysis/src/check/compare_impl_item.rs index 6edd68f1bae..69a02b73a79 100644 --- a/compiler/rustc_hir_analysis/src/check/compare_impl_item.rs +++ b/compiler/rustc_hir_analysis/src/check/compare_impl_item.rs @@ -125,9 +125,9 @@ fn check_method_is_structurally_compatible<'tcx>( /// <'b> fn(t: &'i0 U0, m: &'b N0) -> Foo /// ``` /// -/// We now want to extract and substitute the type of the *trait* +/// We now want to extract and instantiate the type of the *trait* /// method and compare it. To do so, we must create a compound -/// substitution by combining `trait_to_impl_args` and +/// instantiation by combining `trait_to_impl_args` and /// `impl_to_placeholder_args`, and also adding a mapping for the method /// type parameters. We extend the mapping to also include /// the method parameters. @@ -146,11 +146,11 @@ fn check_method_is_structurally_compatible<'tcx>( /// vs `'b`). However, the normal subtyping rules on fn types handle /// this kind of equivalency just fine. /// -/// We now use these substitutions to ensure that all declared bounds are -/// satisfied by the implementation's method. +/// We now use these generic parameters to ensure that all declared bounds +/// are satisfied by the implementation's method. /// /// We do this by creating a parameter environment which contains a -/// substitution corresponding to `impl_to_placeholder_args`. We then build +/// generic parameter corresponding to `impl_to_placeholder_args`. We then build /// `trait_to_placeholder_args` and use it to convert the predicates contained /// in the `trait_m` generics to the placeholder form. /// @@ -454,7 +454,7 @@ pub(super) fn collect_return_position_impl_trait_in_trait_tys<'tcx>( let impl_trait_ref = tcx.impl_trait_ref(impl_m.impl_container(tcx).unwrap()).unwrap().instantiate_identity(); // First, check a few of the same things as `compare_impl_method`, - // just so we don't ICE during substitution later. + // just so we don't ICE during instantiation later. check_method_is_structurally_compatible(tcx, impl_m, trait_m, impl_trait_ref, true)?; let trait_to_impl_args = impl_trait_ref.args; @@ -543,7 +543,7 @@ pub(super) fn collect_return_position_impl_trait_in_trait_tys<'tcx>( // } // ``` // .. to compile. However, since we use both the normalized and unnormalized - // inputs and outputs from the substituted trait signature, we will end up + // inputs and outputs from the instantiated trait signature, we will end up // seeing the hidden type of an RPIT in the signature itself. Naively, this // means that we will use the hidden type to imply the hidden type's own // well-formedness. @@ -699,7 +699,7 @@ pub(super) fn collect_return_position_impl_trait_in_trait_tys<'tcx>( // NOTE(compiler-errors): RPITITs, like all other RPITs, have early-bound // region args that are synthesized during AST lowering. These are args // that are appended to the parent args (trait and trait method). However, - // we're trying to infer the unsubstituted type value of the RPITIT inside + // we're trying to infer the uninstantiated type value of the RPITIT inside // the *impl*, so we can later use the impl's method args to normalize // an RPITIT to a concrete type (`confirm_impl_trait_in_trait_candidate`). // @@ -711,7 +711,7 @@ pub(super) fn collect_return_position_impl_trait_in_trait_tys<'tcx>( // guarantee that the indices from the trait args and impl args line up. // So to fix this, we subtract the number of trait args and add the number of // impl args to *renumber* these early-bound regions to their corresponding - // indices in the impl's substitutions list. + // indices in the impl's generic parameters list. // // Also, we only need to account for a difference in trait and impl args, // since we previously enforce that the trait method and impl method have the diff --git a/compiler/rustc_hir_analysis/src/check/dropck.rs b/compiler/rustc_hir_analysis/src/check/dropck.rs index 7b60457affa..82a6b6b6f2c 100644 --- a/compiler/rustc_hir_analysis/src/check/dropck.rs +++ b/compiler/rustc_hir_analysis/src/check/dropck.rs @@ -124,14 +124,14 @@ fn ensure_drop_predicates_are_implied_by_item_defn<'tcx>( let infcx = tcx.infer_ctxt().build(); let ocx = ObligationCtxt::new(&infcx); - // Take the param-env of the adt and substitute the args that show up in + // Take the param-env of the adt and instantiate the args that show up in // the implementation's self type. This gives us the assumptions that the // self ty of the implementation is allowed to know just from it being a // well-formed adt, since that's all we're allowed to assume while proving // the Drop implementation is not specialized. // // We don't need to normalize this param-env or anything, since we're only - // substituting it with free params, so no additional param-env normalization + // instantiating it with free params, so no additional param-env normalization // can occur on top of what has been done in the param_env query itself. let param_env = ty::EarlyBinder::bind(tcx.param_env(adt_def_id)).instantiate(tcx, adt_to_impl_args); diff --git a/compiler/rustc_hir_analysis/src/check/mod.rs b/compiler/rustc_hir_analysis/src/check/mod.rs index b7443198311..2f8e065df33 100644 --- a/compiler/rustc_hir_analysis/src/check/mod.rs +++ b/compiler/rustc_hir_analysis/src/check/mod.rs @@ -56,7 +56,7 @@ type variable is an instance of a type parameter. That is, given a generic function `fn foo<T>(t: T)`, while checking the function `foo`, the type `ty_param(0)` refers to the type `T`, which is treated in abstract. However, when `foo()` is called, `T` will be -substituted for a fresh type variable `N`. This variable will +instantiated with a fresh type variable `N`. This variable will eventually be resolved to some concrete type (which might itself be a type parameter). diff --git a/compiler/rustc_hir_analysis/src/check/region.rs b/compiler/rustc_hir_analysis/src/check/region.rs index 1c0a1a69513..0f5fd7e99b7 100644 --- a/compiler/rustc_hir_analysis/src/check/region.rs +++ b/compiler/rustc_hir_analysis/src/check/region.rs @@ -16,7 +16,6 @@ use rustc_index::Idx; use rustc_middle::middle::region::*; use rustc_middle::ty::TyCtxt; use rustc_span::source_map; -use rustc_span::Span; use super::errs::{maybe_expr_static_mut, maybe_stmt_static_mut}; @@ -72,11 +71,7 @@ struct RegionResolutionVisitor<'tcx> { } /// Records the lifetime of a local variable as `cx.var_parent` -fn record_var_lifetime( - visitor: &mut RegionResolutionVisitor<'_>, - var_id: hir::ItemLocalId, - _sp: Span, -) { +fn record_var_lifetime(visitor: &mut RegionResolutionVisitor<'_>, var_id: hir::ItemLocalId) { match visitor.cx.var_parent { None => { // this can happen in extern fn declarations like @@ -210,7 +205,7 @@ fn resolve_pat<'tcx>(visitor: &mut RegionResolutionVisitor<'tcx>, pat: &'tcx hir // If this is a binding then record the lifetime of that binding. if let PatKind::Binding(..) = pat.kind { - record_var_lifetime(visitor, pat.hir_id.local_id, pat.span); + record_var_lifetime(visitor, pat.hir_id.local_id); } debug!("resolve_pat - pre-increment {} pat = {:?}", visitor.expr_and_pat_count, pat); diff --git a/compiler/rustc_hir_analysis/src/check/wfcheck.rs b/compiler/rustc_hir_analysis/src/check/wfcheck.rs index 646a84b043c..9541a0bcc48 100644 --- a/compiler/rustc_hir_analysis/src/check/wfcheck.rs +++ b/compiler/rustc_hir_analysis/src/check/wfcheck.rs @@ -118,9 +118,9 @@ where return Err(err); } else { // HACK(oli-obk): tests/ui/specialization/min_specialization/specialize_on_type_error.rs - // causes an error (span_delayed_bug) during normalization, without reporting an error, - // so we need to act as if no error happened, in order to let our callers continue and - // report an error later in check_impl_items_against_trait. + // causes an delayed bug during normalization, without reporting an error, so we need + // to act as if no error happened, in order to let our callers continue and report an + // error later in check_impl_items_against_trait. return Ok(()); } } @@ -618,7 +618,7 @@ fn gather_gat_bounds<'tcx, T: TypeFoldable<TyCtxt<'tcx>>>( // The bounds we that we would require from `to_check` let mut bounds = FxHashSet::default(); - let (regions, types) = GATSubstCollector::visit(gat_def_id.to_def_id(), to_check); + let (regions, types) = GATArgsCollector::visit(gat_def_id.to_def_id(), to_check); // If both regions and types are empty, then this GAT isn't in the // set of types we are checking, and we shouldn't try to do clause analysis @@ -787,34 +787,34 @@ fn test_region_obligations<'tcx>( /// `<P0 as Trait<P1..Pn>>::GAT<Pn..Pm>` and adds the arguments `P0..Pm` into /// the two vectors, `regions` and `types` (depending on their kind). For each /// parameter `Pi` also track the index `i`. -struct GATSubstCollector<'tcx> { +struct GATArgsCollector<'tcx> { gat: DefId, - // Which region appears and which parameter index its substituted for + // Which region appears and which parameter index its instantiated with regions: FxHashSet<(ty::Region<'tcx>, usize)>, - // Which params appears and which parameter index its substituted for + // Which params appears and which parameter index its instantiated with types: FxHashSet<(Ty<'tcx>, usize)>, } -impl<'tcx> GATSubstCollector<'tcx> { +impl<'tcx> GATArgsCollector<'tcx> { fn visit<T: TypeFoldable<TyCtxt<'tcx>>>( gat: DefId, t: T, ) -> (FxHashSet<(ty::Region<'tcx>, usize)>, FxHashSet<(Ty<'tcx>, usize)>) { let mut visitor = - GATSubstCollector { gat, regions: FxHashSet::default(), types: FxHashSet::default() }; + GATArgsCollector { gat, regions: FxHashSet::default(), types: FxHashSet::default() }; t.visit_with(&mut visitor); (visitor.regions, visitor.types) } } -impl<'tcx> TypeVisitor<TyCtxt<'tcx>> for GATSubstCollector<'tcx> { +impl<'tcx> TypeVisitor<TyCtxt<'tcx>> for GATArgsCollector<'tcx> { type BreakTy = !; fn visit_ty(&mut self, t: Ty<'tcx>) -> ControlFlow<Self::BreakTy> { match t.kind() { ty::Alias(ty::Projection, p) if p.def_id == self.gat => { - for (idx, subst) in p.args.iter().enumerate() { - match subst.unpack() { + for (idx, arg) in p.args.iter().enumerate() { + match arg.unpack() { GenericArgKind::Lifetime(lt) if !lt.is_bound() => { self.regions.insert((lt, idx)); } @@ -1407,14 +1407,14 @@ fn check_where_clauses<'tcx>(wfcx: &WfCheckingCtxt<'_, 'tcx>, span: Span, def_id } } - // Check that trait predicates are WF when params are substituted by their defaults. + // Check that trait predicates are WF when params are instantiated with their defaults. // We don't want to overly constrain the predicates that may be written but we want to // catch cases where a default my never be applied such as `struct Foo<T: Copy = String>`. // Therefore we check if a predicate which contains a single type param - // with a concrete default is WF with that default substituted. + // with a concrete default is WF with that default instantiated. // For more examples see tests `defaults-well-formedness.rs` and `type-check-defaults.rs`. // - // First we build the defaulted substitution. + // First we build the defaulted generic parameters. let args = GenericArgs::for_item(tcx, def_id.to_def_id(), |param, _| { match param.kind { GenericParamDefKind::Lifetime => { @@ -1428,7 +1428,7 @@ fn check_where_clauses<'tcx>(wfcx: &WfCheckingCtxt<'_, 'tcx>, span: Span, def_id let default_ty = tcx.type_of(param.def_id).instantiate_identity(); // ... and it's not a dependent default, ... if !default_ty.has_param() { - // ... then substitute it with the default. + // ... then instantiate it with the default. return default_ty.into(); } } @@ -1441,7 +1441,7 @@ fn check_where_clauses<'tcx>(wfcx: &WfCheckingCtxt<'_, 'tcx>, span: Span, def_id let default_ct = tcx.const_param_default(param.def_id).instantiate_identity(); // ... and it's not a dependent default, ... if !default_ct.has_param() { - // ... then substitute it with the default. + // ... then instantiate it with the default. return default_ct.into(); } } @@ -1451,7 +1451,7 @@ fn check_where_clauses<'tcx>(wfcx: &WfCheckingCtxt<'_, 'tcx>, span: Span, def_id } }); - // Now we build the substituted predicates. + // Now we build the instantiated predicates. let default_obligations = predicates .predicates .iter() @@ -1483,23 +1483,25 @@ fn check_where_clauses<'tcx>(wfcx: &WfCheckingCtxt<'_, 'tcx>, span: Span, def_id } let mut param_count = CountParams::default(); let has_region = pred.visit_with(&mut param_count).is_break(); - let substituted_pred = ty::EarlyBinder::bind(pred).instantiate(tcx, args); + let instantiated_pred = ty::EarlyBinder::bind(pred).instantiate(tcx, args); // Don't check non-defaulted params, dependent defaults (including lifetimes) // or preds with multiple params. - if substituted_pred.has_non_region_param() || param_count.params.len() > 1 || has_region + if instantiated_pred.has_non_region_param() + || param_count.params.len() > 1 + || has_region { None - } else if predicates.predicates.iter().any(|&(p, _)| p == substituted_pred) { + } else if predicates.predicates.iter().any(|&(p, _)| p == instantiated_pred) { // Avoid duplication of predicates that contain no parameters, for example. None } else { - Some((substituted_pred, sp)) + Some((instantiated_pred, sp)) } }) .map(|(pred, sp)| { // Convert each of those into an obligation. So if you have // something like `struct Foo<T: Copy = String>`, we would - // take that predicate `T: Copy`, substitute to `String: Copy` + // take that predicate `T: Copy`, instantiated with `String: Copy` // (actually that happens in the previous `flat_map` call), // and then try to prove it (in this case, we'll fail). // @@ -1635,6 +1637,12 @@ fn check_method_receiver<'tcx>( let receiver_ty = sig.inputs()[0]; let receiver_ty = wfcx.normalize(span, None, receiver_ty); + // If the receiver already has errors reported, consider it valid to avoid + // unnecessary errors (#58712). + if receiver_ty.references_error() { + return Ok(()); + } + if tcx.features().arbitrary_self_types { if !receiver_is_valid(wfcx, span, receiver_ty, self_ty, true) { // Report error; `arbitrary_self_types` was enabled. @@ -1749,9 +1757,7 @@ fn receiver_is_valid<'tcx>( } } else { debug!("receiver_is_valid: type `{:?}` does not deref to `{:?}`", receiver_ty, self_ty); - // If the receiver already has errors reported due to it, consider it valid to avoid - // unnecessary errors (#58712). - return receiver_ty.references_error(); + return false; } } diff --git a/compiler/rustc_hir_analysis/src/coherence/builtin.rs b/compiler/rustc_hir_analysis/src/coherence/builtin.rs index fc911ecdad2..370c6c607d7 100644 --- a/compiler/rustc_hir_analysis/src/coherence/builtin.rs +++ b/compiler/rustc_hir_analysis/src/coherence/builtin.rs @@ -396,7 +396,7 @@ pub fn coerce_unsized_info<'tcx>( // // To check if this impl is legal, we would walk down // the fields of `Foo` and consider their types with - // both substitutes. We are looking to find that + // both generic parameters. We are looking to find that // exactly one (non-phantom) field has changed its // type, which we will expect to be the pointer that // is becoming fat (we could probably generalize this diff --git a/compiler/rustc_hir_analysis/src/collect.rs b/compiler/rustc_hir_analysis/src/collect.rs index f458ff01c10..d92e1a14151 100644 --- a/compiler/rustc_hir_analysis/src/collect.rs +++ b/compiler/rustc_hir_analysis/src/collect.rs @@ -31,6 +31,7 @@ use rustc_middle::ty::util::{Discr, IntTypeExt}; use rustc_middle::ty::{self, AdtKind, Const, IsSuggestable, ToPredicate, Ty, TyCtxt}; use rustc_span::symbol::{kw, sym, Ident, Symbol}; use rustc_span::Span; +use rustc_target::abi::FieldIdx; use rustc_target::spec::abi; use rustc_trait_selection::infer::InferCtxtExt; use rustc_trait_selection::traits::error_reporting::suggestions::NextTypeParamName; @@ -84,6 +85,7 @@ pub fn provide(providers: &mut Providers) { coroutine_for_closure, collect_mod_item_types, is_type_alias_impl_trait, + find_field, ..*providers }; } @@ -789,6 +791,175 @@ fn convert_enum_variant_types(tcx: TyCtxt<'_>, def_id: DefId) { } } +fn find_field(tcx: TyCtxt<'_>, (def_id, ident): (DefId, Ident)) -> Option<FieldIdx> { + tcx.adt_def(def_id).non_enum_variant().fields.iter_enumerated().find_map(|(idx, field)| { + if field.is_unnamed() { + let field_ty = tcx.type_of(field.did).instantiate_identity(); + let adt_def = field_ty.ty_adt_def().expect("expect Adt for unnamed field"); + tcx.find_field((adt_def.did(), ident)).map(|_| idx) + } else { + (field.ident(tcx).normalize_to_macros_2_0() == ident).then_some(idx) + } + }) +} + +#[derive(Clone, Copy)] +struct NestedSpan { + span: Span, + nested_field_span: Span, +} + +impl NestedSpan { + fn to_field_already_declared_nested_help(&self) -> errors::FieldAlreadyDeclaredNestedHelp { + errors::FieldAlreadyDeclaredNestedHelp { span: self.span } + } +} + +#[derive(Clone, Copy)] +enum FieldDeclSpan { + NotNested(Span), + Nested(NestedSpan), +} + +impl From<Span> for FieldDeclSpan { + fn from(span: Span) -> Self { + Self::NotNested(span) + } +} + +impl From<NestedSpan> for FieldDeclSpan { + fn from(span: NestedSpan) -> Self { + Self::Nested(span) + } +} + +struct FieldUniquenessCheckContext<'tcx> { + tcx: TyCtxt<'tcx>, + seen_fields: FxHashMap<Ident, FieldDeclSpan>, +} + +impl<'tcx> FieldUniquenessCheckContext<'tcx> { + fn new(tcx: TyCtxt<'tcx>) -> Self { + Self { tcx, seen_fields: FxHashMap::default() } + } + + /// Check if a given field `ident` declared at `field_decl` has been declared elsewhere before. + fn check_field_decl(&mut self, ident: Ident, field_decl: FieldDeclSpan) { + use FieldDeclSpan::*; + let field_name = ident.name; + let ident = ident.normalize_to_macros_2_0(); + match (field_decl, self.seen_fields.get(&ident).copied()) { + (NotNested(span), Some(NotNested(prev_span))) => { + self.tcx.dcx().emit_err(errors::FieldAlreadyDeclared::NotNested { + field_name, + span, + prev_span, + }); + } + (NotNested(span), Some(Nested(prev))) => { + self.tcx.dcx().emit_err(errors::FieldAlreadyDeclared::PreviousNested { + field_name, + span, + prev_span: prev.span, + prev_nested_field_span: prev.nested_field_span, + prev_help: prev.to_field_already_declared_nested_help(), + }); + } + ( + Nested(current @ NestedSpan { span, nested_field_span, .. }), + Some(NotNested(prev_span)), + ) => { + self.tcx.dcx().emit_err(errors::FieldAlreadyDeclared::CurrentNested { + field_name, + span, + nested_field_span, + help: current.to_field_already_declared_nested_help(), + prev_span, + }); + } + (Nested(current @ NestedSpan { span, nested_field_span }), Some(Nested(prev))) => { + self.tcx.dcx().emit_err(errors::FieldAlreadyDeclared::BothNested { + field_name, + span, + nested_field_span, + help: current.to_field_already_declared_nested_help(), + prev_span: prev.span, + prev_nested_field_span: prev.nested_field_span, + prev_help: prev.to_field_already_declared_nested_help(), + }); + } + (field_decl, None) => { + self.seen_fields.insert(ident, field_decl); + } + } + } + + /// Check the uniqueness of fields across adt where there are + /// nested fields imported from an unnamed field. + fn check_field_in_nested_adt(&mut self, adt_def: ty::AdtDef<'_>, unnamed_field_span: Span) { + for field in adt_def.all_fields() { + if field.is_unnamed() { + // Here we don't care about the generic parameters, so `instantiate_identity` is enough. + match self.tcx.type_of(field.did).instantiate_identity().kind() { + ty::Adt(adt_def, _) => { + self.check_field_in_nested_adt(*adt_def, unnamed_field_span); + } + ty_kind => span_bug!( + self.tcx.def_span(field.did), + "Unexpected TyKind in FieldUniquenessCheckContext::check_field_in_nested_adt(): {ty_kind:?}" + ), + } + } else { + self.check_field_decl( + field.ident(self.tcx), + NestedSpan { + span: unnamed_field_span, + nested_field_span: self.tcx.def_span(field.did), + } + .into(), + ); + } + } + } + + /// Check the uniqueness of fields in a struct variant, and recursively + /// check the nested fields if it is an unnamed field with type of an + /// annoymous adt. + fn check_field(&mut self, field: &hir::FieldDef<'_>) { + if field.ident.name != kw::Underscore { + self.check_field_decl(field.ident, field.span.into()); + return; + } + match &field.ty.kind { + hir::TyKind::AnonAdt(item_id) => { + match &self.tcx.hir_node(item_id.hir_id()).expect_item().kind { + hir::ItemKind::Struct(variant_data, ..) + | hir::ItemKind::Union(variant_data, ..) => { + variant_data.fields().iter().for_each(|f| self.check_field(f)); + } + item_kind => span_bug!( + field.ty.span, + "Unexpected ItemKind in FieldUniquenessCheckContext::check_field(): {item_kind:?}" + ), + } + } + hir::TyKind::Path(hir::QPath::Resolved(_, hir::Path { res, .. })) => { + self.check_field_in_nested_adt(self.tcx.adt_def(res.def_id()), field.span); + } + // Abort due to errors (there must be an error if an unnamed field + // has any type kind other than an anonymous adt or a named adt) + ty_kind => { + self.tcx.dcx().span_delayed_bug( + field.ty.span, + format!("Unexpected TyKind in FieldUniquenessCheckContext::check_field(): {ty_kind:?}"), + ); + // FIXME: errors during AST validation should abort the compilation before reaching here. + self.tcx.dcx().abort_if_errors(); + } + } + } +} + fn convert_variant( tcx: TyCtxt<'_>, variant_did: Option<LocalDefId>, @@ -797,29 +968,26 @@ fn convert_variant( def: &hir::VariantData<'_>, adt_kind: ty::AdtKind, parent_did: LocalDefId, + is_anonymous: bool, ) -> ty::VariantDef { - let mut seen_fields: FxHashMap<Ident, Span> = Default::default(); + let mut has_unnamed_fields = false; + let mut field_uniqueness_check_ctx = FieldUniquenessCheckContext::new(tcx); let fields = def .fields() .iter() - .map(|f| { - let dup_span = seen_fields.get(&f.ident.normalize_to_macros_2_0()).cloned(); - if let Some(prev_span) = dup_span { - tcx.dcx().emit_err(errors::FieldAlreadyDeclared { - field_name: f.ident, - span: f.span, - prev_span, - }); - } else { - seen_fields.insert(f.ident.normalize_to_macros_2_0(), f.span); - } - - ty::FieldDef { - did: f.def_id.to_def_id(), - name: f.ident.name, - vis: tcx.visibility(f.def_id), + .inspect(|f| { + has_unnamed_fields |= f.ident.name == kw::Underscore; + // We only check named ADT here because anonymous ADTs are checked inside + // the nammed ADT in which they are defined. + if !is_anonymous { + field_uniqueness_check_ctx.check_field(f); } }) + .map(|f| ty::FieldDef { + did: f.def_id.to_def_id(), + name: f.ident.name, + vis: tcx.visibility(f.def_id), + }) .collect(); let recovered = match def { hir::VariantData::Struct { recovered, .. } => *recovered, @@ -837,6 +1005,7 @@ fn convert_variant( adt_kind == AdtKind::Struct && tcx.has_attr(parent_did, sym::non_exhaustive) || variant_did .is_some_and(|variant_did| tcx.has_attr(variant_did, sym::non_exhaustive)), + has_unnamed_fields, ) } @@ -847,7 +1016,12 @@ fn adt_def(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::AdtDef<'_> { bug!("expected ADT to be an item"); }; - let repr = tcx.repr_options_of_def(def_id.to_def_id()); + let is_anonymous = item.ident.name == kw::Empty; + let repr = if is_anonymous { + tcx.adt_def(tcx.local_parent(def_id)).repr() + } else { + tcx.repr_options_of_def(def_id.to_def_id()) + }; let (kind, variants) = match &item.kind { ItemKind::Enum(def, _) => { let mut distance_from_explicit = 0; @@ -871,6 +1045,7 @@ fn adt_def(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::AdtDef<'_> { &v.data, AdtKind::Enum, def_id, + is_anonymous, ) }) .collect(); @@ -890,6 +1065,7 @@ fn adt_def(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::AdtDef<'_> { def, adt_kind, def_id, + is_anonymous, )) .collect(); @@ -897,7 +1073,7 @@ fn adt_def(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::AdtDef<'_> { } _ => bug!("{:?} is not an ADT", item.owner_id.def_id), }; - tcx.mk_adt_def(def_id.to_def_id(), kind, variants, repr) + tcx.mk_adt_def(def_id.to_def_id(), kind, variants, repr, is_anonymous) } fn trait_def(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::TraitDef { diff --git a/compiler/rustc_hir_analysis/src/collect/generics_of.rs b/compiler/rustc_hir_analysis/src/collect/generics_of.rs index e5e731bbe8c..9cc6c16c126 100644 --- a/compiler/rustc_hir_analysis/src/collect/generics_of.rs +++ b/compiler/rustc_hir_analysis/src/collect/generics_of.rs @@ -71,7 +71,7 @@ pub(super) fn generics_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::Generics { // end up with that const looking like: `ty::ConstKind::Unevaluated(def_id, args: [N#0])`. // // This causes ICEs (#86580) when building the args for Foo in `fn foo() -> Foo { .. }` as - // we substitute the defaults with the partially built args when we build the args. Subst'ing + // we instantiate the defaults with the partially built args when we build the args. Instantiating // the `N#0` on the unevaluated const indexes into the empty args we're in the process of building. // // We fix this by having this function return the parent's generics ourselves and truncating the diff --git a/compiler/rustc_hir_analysis/src/collect/resolve_bound_vars.rs b/compiler/rustc_hir_analysis/src/collect/resolve_bound_vars.rs index 1aa9c6929f8..c9cf43ddfc8 100644 --- a/compiler/rustc_hir_analysis/src/collect/resolve_bound_vars.rs +++ b/compiler/rustc_hir_analysis/src/collect/resolve_bound_vars.rs @@ -1786,7 +1786,8 @@ impl<'a, 'tcx> BoundVarContext<'a, 'tcx> { let bound_predicate = pred.kind(); match bound_predicate.skip_binder() { ty::ClauseKind::Trait(data) => { - // The order here needs to match what we would get from `subst_supertrait` + // The order here needs to match what we would get from + // `rustc_middle::ty::predicate::Clause::instantiate_supertrait` let pred_bound_vars = bound_predicate.bound_vars(); let mut all_bound_vars = bound_vars.clone(); all_bound_vars.extend(pred_bound_vars.iter()); diff --git a/compiler/rustc_hir_analysis/src/constrained_generic_params.rs b/compiler/rustc_hir_analysis/src/constrained_generic_params.rs index 65d1ffa40e2..05efad3ccb3 100644 --- a/compiler/rustc_hir_analysis/src/constrained_generic_params.rs +++ b/compiler/rustc_hir_analysis/src/constrained_generic_params.rs @@ -119,7 +119,7 @@ pub fn identify_constrained_generic_params<'tcx>( /// * `<U as Iterator>::Item = T` -- a desugared ProjectionPredicate /// /// When we, for example, try to go over the trait-reference -/// `IntoIter<u32> as Trait`, we substitute the impl parameters with fresh +/// `IntoIter<u32> as Trait`, we instantiate the impl parameters with fresh /// variables and match them with the impl trait-ref, so we know that /// `$U = IntoIter<u32>`. /// diff --git a/compiler/rustc_hir_analysis/src/errors.rs b/compiler/rustc_hir_analysis/src/errors.rs index bec53693d6c..6a505b96197 100644 --- a/compiler/rustc_hir_analysis/src/errors.rs +++ b/compiler/rustc_hir_analysis/src/errors.rs @@ -175,14 +175,66 @@ pub struct DropImplOnWrongItem { } #[derive(Diagnostic)] -#[diag(hir_analysis_field_already_declared, code = E0124)] -pub struct FieldAlreadyDeclared { - pub field_name: Ident, +pub enum FieldAlreadyDeclared { + #[diag(hir_analysis_field_already_declared, code = E0124)] + NotNested { + field_name: Symbol, + #[primary_span] + #[label] + span: Span, + #[label(hir_analysis_previous_decl_label)] + prev_span: Span, + }, + #[diag(hir_analysis_field_already_declared_current_nested)] + CurrentNested { + field_name: Symbol, + #[primary_span] + #[label] + span: Span, + #[note(hir_analysis_nested_field_decl_note)] + nested_field_span: Span, + #[subdiagnostic] + help: FieldAlreadyDeclaredNestedHelp, + #[label(hir_analysis_previous_decl_label)] + prev_span: Span, + }, + #[diag(hir_analysis_field_already_declared_previous_nested)] + PreviousNested { + field_name: Symbol, + #[primary_span] + #[label] + span: Span, + #[label(hir_analysis_previous_decl_label)] + prev_span: Span, + #[note(hir_analysis_previous_nested_field_decl_note)] + prev_nested_field_span: Span, + #[subdiagnostic] + prev_help: FieldAlreadyDeclaredNestedHelp, + }, + #[diag(hir_analysis_field_already_declared_both_nested)] + BothNested { + field_name: Symbol, + #[primary_span] + #[label] + span: Span, + #[note(hir_analysis_nested_field_decl_note)] + nested_field_span: Span, + #[subdiagnostic] + help: FieldAlreadyDeclaredNestedHelp, + #[label(hir_analysis_previous_decl_label)] + prev_span: Span, + #[note(hir_analysis_previous_nested_field_decl_note)] + prev_nested_field_span: Span, + #[subdiagnostic] + prev_help: FieldAlreadyDeclaredNestedHelp, + }, +} + +#[derive(Subdiagnostic)] +#[help(hir_analysis_field_already_declared_nested_help)] +pub struct FieldAlreadyDeclaredNestedHelp { #[primary_span] - #[label] pub span: Span, - #[label(hir_analysis_previous_decl_label)] - pub prev_span: Span, } #[derive(Diagnostic)] @@ -372,8 +424,8 @@ pub struct ManualImplementation { } #[derive(Diagnostic)] -#[diag(hir_analysis_substs_on_overridden_impl)] -pub struct SubstsOnOverriddenImpl { +#[diag(hir_analysis_generic_args_on_overridden_impl)] +pub struct GenericArgsOnOverriddenImpl { #[primary_span] pub span: Span, } @@ -1534,3 +1586,38 @@ pub(crate) enum UnusedGenericParameterHelp { #[help(hir_analysis_unused_generic_parameter_ty_alias_help)] TyAlias { param_name: Ident }, } + +#[derive(Diagnostic)] +pub enum UnnamedFieldsRepr<'a> { + #[diag(hir_analysis_unnamed_fields_repr_missing_repr_c)] + MissingReprC { + #[primary_span] + #[label] + span: Span, + adt_kind: &'static str, + adt_name: Symbol, + #[subdiagnostic] + unnamed_fields: Vec<UnnamedFieldsReprFieldDefined>, + #[suggestion(code = "#[repr(C)]\n")] + sugg_span: Span, + }, + #[diag(hir_analysis_unnamed_fields_repr_field_missing_repr_c)] + FieldMissingReprC { + #[primary_span] + #[label] + span: Span, + #[label(hir_analysis_field_ty_label)] + field_ty_span: Span, + field_ty: Ty<'a>, + field_adt_kind: &'static str, + #[suggestion(code = "#[repr(C)]\n")] + sugg_span: Span, + }, +} + +#[derive(Subdiagnostic)] +#[note(hir_analysis_unnamed_fields_repr_field_defined)] +pub struct UnnamedFieldsReprFieldDefined { + #[primary_span] + pub span: Span, +} diff --git a/compiler/rustc_hir_analysis/src/impl_wf_check/min_specialization.rs b/compiler/rustc_hir_analysis/src/impl_wf_check/min_specialization.rs index 1b6a39d8162..c8dedb0f371 100644 --- a/compiler/rustc_hir_analysis/src/impl_wf_check/min_specialization.rs +++ b/compiler/rustc_hir_analysis/src/impl_wf_check/min_specialization.rs @@ -34,8 +34,8 @@ //! impl<T, I: Iterator<Item=T>> SpecExtend<T> for I { /* default impl */ } //! ``` //! -//! We get that the subst for `impl2` are `[T, std::vec::IntoIter<T>]`. `T` is -//! constrained to be `<I as Iterator>::Item`, so we check only +//! We get that the generic pamameters for `impl2` are `[T, std::vec::IntoIter<T>]`. +//! `T` is constrained to be `<I as Iterator>::Item`, so we check only //! `std::vec::IntoIter<T>` for repeated parameters, which it doesn't have. The //! predicates of `impl1` are only `T: Sized`, which is also a predicate of //! `impl2`. So this specialization is sound. @@ -65,7 +65,7 @@ //! cause use after frees with purely safe code in the same way as specializing //! on traits with methods can. -use crate::errors::SubstsOnOverriddenImpl; +use crate::errors::GenericArgsOnOverriddenImpl; use crate::{constrained_generic_params as cgp, errors}; use rustc_data_structures::fx::FxHashSet; @@ -179,8 +179,8 @@ fn check_constness( } /// Given a specializing impl `impl1`, and the base impl `impl2`, returns two -/// substitutions `(S1, S2)` that equate their trait references. The returned -/// types are expressed in terms of the generics of `impl1`. +/// generic parameters `(S1, S2)` that equate their trait references. +/// The returned types are expressed in terms of the generics of `impl1`. /// /// Example /// @@ -228,13 +228,13 @@ fn get_impl_args( let _ = ocx.resolve_regions_and_report_errors(impl1_def_id, &outlives_env); let Ok(impl2_args) = infcx.fully_resolve(impl2_args) else { let span = tcx.def_span(impl1_def_id); - let guar = tcx.dcx().emit_err(SubstsOnOverriddenImpl { span }); + let guar = tcx.dcx().emit_err(GenericArgsOnOverriddenImpl { span }); return Err(guar); }; Ok((impl1_args, impl2_args)) } -/// Returns a list of all of the unconstrained subst of the given impl. +/// Returns a list of all of the unconstrained generic parameters of the given impl. /// /// For example given the impl: /// @@ -425,9 +425,7 @@ fn check_predicates<'tcx>( let mut res = Ok(()); for (clause, span) in impl1_predicates { - if !impl2_predicates - .iter() - .any(|pred2| trait_predicates_eq(tcx, clause.as_predicate(), *pred2, span)) + if !impl2_predicates.iter().any(|pred2| trait_predicates_eq(clause.as_predicate(), *pred2)) { res = res.and(check_specialization_on(tcx, clause, span)) } @@ -459,10 +457,8 @@ fn check_predicates<'tcx>( /// /// So we make that check in this function and try to raise a helpful error message. fn trait_predicates_eq<'tcx>( - _tcx: TyCtxt<'tcx>, predicate1: ty::Predicate<'tcx>, predicate2: ty::Predicate<'tcx>, - _span: Span, ) -> bool { // FIXME(effects) predicate1 == predicate2 diff --git a/compiler/rustc_hir_analysis/src/outlives/implicit_infer.rs b/compiler/rustc_hir_analysis/src/outlives/implicit_infer.rs index 0cb38094cec..0c0dbbe7ad9 100644 --- a/compiler/rustc_hir_analysis/src/outlives/implicit_infer.rs +++ b/compiler/rustc_hir_analysis/src/outlives/implicit_infer.rs @@ -229,7 +229,7 @@ fn insert_required_predicates_to_be_wf<'tcx>( /// Here, we should fetch the explicit predicates, which /// will give us `U: 'static` and `U: Outer`. The latter we /// can ignore, but we will want to process `U: 'static`, -/// applying the substitution as above. +/// applying the instantiation as above. fn check_explicit_predicates<'tcx>( tcx: TyCtxt<'tcx>, def_id: DefId, @@ -316,7 +316,7 @@ fn check_explicit_predicates<'tcx>( /// Here, when processing the type of field `outer`, we would request the /// set of implicit predicates computed for `Inner` thus far. This will /// initially come back empty, but in next round we will get `U: 'b`. -/// We then apply the substitution `['b => 'a, U => T]` and thus get the +/// We then apply the instantiation `['b => 'a, U => T]` and thus get the /// requirement that `T: 'a` holds for `Outer`. fn check_inferred_predicates<'tcx>( tcx: TyCtxt<'tcx>, @@ -334,7 +334,7 @@ fn check_inferred_predicates<'tcx>( for (&predicate, &span) in predicates.as_ref().skip_binder() { // `predicate` is `U: 'b` in the example above. - // So apply the substitution to get `T: 'a`. + // So apply the instantiation to get `T: 'a`. let ty::OutlivesPredicate(arg, region) = predicates.rebind(predicate).instantiate(tcx, args); insert_outlives_predicate(tcx, arg, region, span, required_predicates); diff --git a/compiler/rustc_hir_analysis/src/variance/mod.rs b/compiler/rustc_hir_analysis/src/variance/mod.rs index 7d145ea1f23..4d5dcbadc4a 100644 --- a/compiler/rustc_hir_analysis/src/variance/mod.rs +++ b/compiler/rustc_hir_analysis/src/variance/mod.rs @@ -172,16 +172,16 @@ fn variance_of_opaque(tcx: TyCtxt<'_>, item_def_id: LocalDefId) -> &[ty::Varianc trait_ref: ty::TraitRef { def_id: _, args, .. }, polarity: _, }) => { - for subst in &args[1..] { - subst.visit_with(&mut collector); + for arg in &args[1..] { + arg.visit_with(&mut collector); } } ty::ClauseKind::Projection(ty::ProjectionPredicate { projection_ty: ty::AliasTy { args, .. }, term, }) => { - for subst in &args[1..] { - subst.visit_with(&mut collector); + for arg in &args[1..] { + arg.visit_with(&mut collector); } term.visit_with(&mut collector); } |
