diff options
Diffstat (limited to 'compiler/rustc_trait_selection/src')
12 files changed, 112 insertions, 73 deletions
diff --git a/compiler/rustc_trait_selection/src/opaque_types.rs b/compiler/rustc_trait_selection/src/opaque_types.rs index ca547bf88b5..f5bc90e6f96 100644 --- a/compiler/rustc_trait_selection/src/opaque_types.rs +++ b/compiler/rustc_trait_selection/src/opaque_types.rs @@ -722,11 +722,6 @@ where // Skip lifetime parameters of the enclosing item(s) substs.as_closure().tupled_upvars_ty().visit_with(self); - - for upvar_ty in substs.as_closure().upvar_tys() { - upvar_ty.visit_with(self); - } - substs.as_closure().sig_as_fn_ptr_ty().visit_with(self); } @@ -735,11 +730,6 @@ where // Also skip the witness type, because that has no free regions. substs.as_generator().tupled_upvars_ty().visit_with(self); - - for upvar_ty in substs.as_generator().upvar_tys() { - upvar_ty.visit_with(self); - } - substs.as_generator().return_ty().visit_with(self); substs.as_generator().yield_ty().visit_with(self); substs.as_generator().resume_ty().visit_with(self); diff --git a/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs b/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs index d429d889fcc..9feba7bfc49 100644 --- a/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs +++ b/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs @@ -200,6 +200,7 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> { &obligation.predicate, &obligation.cause.code, &mut vec![], + &mut Default::default(), ); err.emit(); @@ -1309,10 +1310,20 @@ impl<'a, 'tcx> InferCtxtPrivExt<'tcx> for InferCtxt<'a, 'tcx> { return None; } } + if self.tcx.impl_polarity(def_id) == ty::ImplPolarity::Negative { + return None; + } Some(imp) }) .collect(), - None => all_impls.map(|def_id| self.tcx.impl_trait_ref(def_id).unwrap()).collect(), + None => all_impls + .filter_map(|def_id| { + if self.tcx.impl_polarity(def_id) == ty::ImplPolarity::Negative { + return None; + } + self.tcx.impl_trait_ref(def_id) + }) + .collect(), } } @@ -1700,6 +1711,7 @@ impl<'a, 'tcx> InferCtxtPrivExt<'tcx> for InferCtxt<'a, 'tcx> { &obligation.predicate, &obligation.cause.code, &mut vec![], + &mut Default::default(), ); self.suggest_unsized_bound_if_applicable(err, obligation); } diff --git a/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs b/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs index 7e92df28ca2..5c185dc4a9f 100644 --- a/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs +++ b/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs @@ -7,6 +7,7 @@ use crate::autoderef::Autoderef; use crate::infer::InferCtxt; use crate::traits::normalize_projection_type; +use rustc_data_structures::fx::FxHashSet; use rustc_data_structures::stack::ensure_sufficient_stack; use rustc_errors::{error_code, struct_span_err, Applicability, DiagnosticBuilder, Style}; use rustc_hir as hir; @@ -158,6 +159,7 @@ pub trait InferCtxtExt<'tcx> { predicate: &T, cause_code: &ObligationCauseCode<'tcx>, obligated_types: &mut Vec<&ty::TyS<'tcx>>, + seen_requirements: &mut FxHashSet<DefId>, ) where T: fmt::Display; @@ -1446,31 +1448,30 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> { }); }; - typeck_results + if let Some(cause) = typeck_results .generator_interior_types .iter() .find(|ty::GeneratorInteriorTypeCause { ty, .. }| ty_matches(ty)) - .map(|cause| { - // Check to see if any awaited expressions have the target type. - let from_awaited_ty = visitor - .awaits - .into_iter() - .map(|id| hir.expect_expr(id)) - .find(|await_expr| { - let ty = typeck_results.expr_ty_adjusted(&await_expr); - debug!( - "maybe_note_obligation_cause_for_async_await: await_expr={:?}", - await_expr - ); - ty_matches(ty) - }) - .map(|expr| expr.span); - let ty::GeneratorInteriorTypeCause { span, scope_span, yield_span, expr, .. } = - cause; + { + // Check to see if any awaited expressions have the target type. + let from_awaited_ty = visitor + .awaits + .into_iter() + .map(|id| hir.expect_expr(id)) + .find(|await_expr| { + let ty = typeck_results.expr_ty_adjusted(&await_expr); + debug!( + "maybe_note_obligation_cause_for_async_await: await_expr={:?}", + await_expr + ); + ty_matches(ty) + }) + .map(|expr| expr.span); + let ty::GeneratorInteriorTypeCause { span, scope_span, yield_span, expr, .. } = cause; - interior_or_upvar_span = Some(GeneratorInteriorOrUpvar::Interior(*span)); - interior_extra_info = Some((*scope_span, *yield_span, *expr, from_awaited_ty)); - }); + interior_or_upvar_span = Some(GeneratorInteriorOrUpvar::Interior(*span)); + interior_extra_info = Some((*scope_span, *yield_span, *expr, from_awaited_ty)); + }; debug!( "maybe_note_obligation_cause_for_async_await: interior_or_upvar={:?} \ @@ -1787,6 +1788,7 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> { &obligation.predicate, next_code.unwrap(), &mut Vec::new(), + &mut Default::default(), ); } @@ -1796,6 +1798,7 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> { predicate: &T, cause_code: &ObligationCauseCode<'tcx>, obligated_types: &mut Vec<&ty::TyS<'tcx>>, + seen_requirements: &mut FxHashSet<DefId>, ) where T: fmt::Display, { @@ -2050,18 +2053,44 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> { &parent_predicate, &data.parent_code, obligated_types, + seen_requirements, ) }); } } ObligationCauseCode::ImplDerivedObligation(ref data) => { - let parent_trait_ref = self.resolve_vars_if_possible(data.parent_trait_ref); + let mut parent_trait_ref = self.resolve_vars_if_possible(data.parent_trait_ref); + let parent_def_id = parent_trait_ref.def_id(); err.note(&format!( "required because of the requirements on the impl of `{}` for `{}`", parent_trait_ref.print_only_trait_path(), parent_trait_ref.skip_binder().self_ty() )); - let parent_predicate = parent_trait_ref.without_const().to_predicate(tcx); + + let mut parent_predicate = parent_trait_ref.without_const().to_predicate(tcx); + let mut data = data; + let mut count = 0; + seen_requirements.insert(parent_def_id); + while let ObligationCauseCode::ImplDerivedObligation(child) = &*data.parent_code { + // Skip redundant recursive obligation notes. See `ui/issue-20413.rs`. + let child_trait_ref = self.resolve_vars_if_possible(child.parent_trait_ref); + let child_def_id = child_trait_ref.def_id(); + if seen_requirements.insert(child_def_id) { + break; + } + count += 1; + data = child; + parent_predicate = child_trait_ref.without_const().to_predicate(tcx); + parent_trait_ref = child_trait_ref; + } + if count > 0 { + err.note(&format!("{} redundant requirements hidden", count)); + err.note(&format!( + "required because of the requirements on the impl of `{}` for `{}`", + parent_trait_ref.print_only_trait_path(), + parent_trait_ref.skip_binder().self_ty() + )); + } // #74711: avoid a stack overflow ensure_sufficient_stack(|| { self.note_obligation_cause_code( @@ -2069,6 +2098,7 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> { &parent_predicate, &data.parent_code, obligated_types, + seen_requirements, ) }); } @@ -2082,20 +2112,21 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> { &parent_predicate, &data.parent_code, obligated_types, + seen_requirements, ) }); } ObligationCauseCode::CompareImplMethodObligation { .. } => { err.note(&format!( - "the requirement `{}` appears on the impl method \ - but not on the corresponding trait method", + "the requirement `{}` appears on the impl method but not on the corresponding \ + trait method", predicate )); } ObligationCauseCode::CompareImplTypeObligation { .. } => { err.note(&format!( - "the requirement `{}` appears on the associated impl type \ - but not on the corresponding associated trait type", + "the requirement `{}` appears on the associated impl type but not on the \ + corresponding associated trait type", predicate )); } diff --git a/compiler/rustc_trait_selection/src/traits/mod.rs b/compiler/rustc_trait_selection/src/traits/mod.rs index 2d7df2ddd11..2fb9b3cd5d3 100644 --- a/compiler/rustc_trait_selection/src/traits/mod.rs +++ b/compiler/rustc_trait_selection/src/traits/mod.rs @@ -97,13 +97,13 @@ impl Default for SkipLeakCheck { /// The mode that trait queries run in. #[derive(Copy, Clone, PartialEq, Eq, Debug)] pub enum TraitQueryMode { - // Standard/un-canonicalized queries get accurate - // spans etc. passed in and hence can do reasonable - // error reporting on their own. + /// Standard/un-canonicalized queries get accurate + /// spans etc. passed in and hence can do reasonable + /// error reporting on their own. Standard, - // Canonicalized queries get dummy spans and hence - // must generally propagate errors to - // pre-canonicalization callsites. + /// Canonicalized queries get dummy spans and hence + /// must generally propagate errors to + /// pre-canonicalization callsites. Canonical, } diff --git a/compiler/rustc_trait_selection/src/traits/project.rs b/compiler/rustc_trait_selection/src/traits/project.rs index dead795c6af..df472e6ed7e 100644 --- a/compiler/rustc_trait_selection/src/traits/project.rs +++ b/compiler/rustc_trait_selection/src/traits/project.rs @@ -997,7 +997,7 @@ fn assemble_candidates_from_impls<'cx, 'tcx>( // type. // // NOTE: This should be kept in sync with the similar code in - // `rustc_ty::instance::resolve_associated_item()`. + // `rustc_ty_utils::instance::resolve_associated_item()`. let node_item = assoc_ty_def(selcx, impl_data.impl_def_id, obligation.predicate.item_def_id) .map_err(|ErrorReported| ())?; diff --git a/compiler/rustc_trait_selection/src/traits/query/normalize.rs b/compiler/rustc_trait_selection/src/traits/query/normalize.rs index 873d300a5e3..33cd509cbb8 100644 --- a/compiler/rustc_trait_selection/src/traits/query/normalize.rs +++ b/compiler/rustc_trait_selection/src/traits/query/normalize.rs @@ -49,7 +49,7 @@ impl<'cx, 'tcx> AtExt<'tcx> for At<'cx, 'tcx> { self.param_env, ); if !value.has_projections() { - return Ok(Normalized { value: value.clone(), obligations: vec![] }); + return Ok(Normalized { value, obligations: vec![] }); } let mut normalizer = QueryNormalizer { @@ -97,6 +97,7 @@ impl<'cx, 'tcx> TypeFolder<'tcx> for QueryNormalizer<'cx, 'tcx> { self.infcx.tcx } + #[instrument(skip(self))] fn fold_ty(&mut self, ty: Ty<'tcx>) -> Ty<'tcx> { if !ty.has_projections() { return ty; diff --git a/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs b/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs index d2556c44fb4..ca3369b8f1e 100644 --- a/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs +++ b/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs @@ -350,11 +350,11 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { // Micro-optimization: filter out predicates relating to different traits. let matching_bounds = - all_bounds.filter(|p| p.def_id() == stack.obligation.predicate.def_id()); + all_bounds.filter(|p| p.value.def_id() == stack.obligation.predicate.def_id()); // Keep only those bounds which may apply, and propagate overflow if it occurs. for bound in matching_bounds { - let wc = self.evaluate_where_clause(stack, bound)?; + let wc = self.evaluate_where_clause(stack, bound.value)?; if wc.may_apply() { candidates.vec.push(ParamCandidate(bound)); } diff --git a/compiler/rustc_trait_selection/src/traits/select/confirmation.rs b/compiler/rustc_trait_selection/src/traits/select/confirmation.rs index 7c155c7684e..ed22d5849e2 100644 --- a/compiler/rustc_trait_selection/src/traits/select/confirmation.rs +++ b/compiler/rustc_trait_selection/src/traits/select/confirmation.rs @@ -8,6 +8,7 @@ //! https://rustc-dev-guide.rust-lang.org/traits/resolution.html#confirmation use rustc_data_structures::stack::ensure_sufficient_stack; use rustc_hir::lang_items::LangItem; +use rustc_hir::Constness; use rustc_index::bit_set::GrowableBitSet; use rustc_infer::infer::InferOk; use rustc_infer::infer::LateBoundRegionConversionTime::HigherRankedType; @@ -55,8 +56,8 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { } ParamCandidate(param) => { - let obligations = self.confirm_param_candidate(obligation, param); - Ok(ImplSource::Param(obligations)) + let obligations = self.confirm_param_candidate(obligation, param.value); + Ok(ImplSource::Param(obligations, param.constness)) } ImplCandidate(impl_def_id) => { @@ -70,7 +71,8 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { ProjectionCandidate(idx) => { let obligations = self.confirm_projection_candidate(obligation, idx)?; - Ok(ImplSource::Param(obligations)) + // FIXME(jschievink): constness + Ok(ImplSource::Param(obligations, Constness::NotConst)) } ObjectCandidate(idx) => { @@ -106,7 +108,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { // This indicates something like `Trait + Send: Send`. In this case, we know that // this holds because that's what the object type is telling us, and there's really // no additional obligations to prove and no types in particular to unify, etc. - Ok(ImplSource::Param(Vec::new())) + Ok(ImplSource::Param(Vec::new(), Constness::NotConst)) } BuiltinUnsizeCandidate => { @@ -151,7 +153,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { obligations.extend(self.infcx.commit_if_ok(|_| { self.infcx .at(&obligation.cause, obligation.param_env) - .sup(placeholder_trait_predicate.trait_ref.to_poly_trait_ref(), candidate) + .sup(placeholder_trait_predicate.trait_ref.to_poly_trait_ref(), candidate.value) .map(|InferOk { obligations, .. }| obligations) .map_err(|_| Unimplemented) })?); @@ -445,7 +447,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { ); nested.push(Obligation::new( obligation.cause.clone(), - obligation.param_env.clone(), + obligation.param_env, normalized_super_trait, )); } @@ -483,7 +485,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { ); nested.push(Obligation::new( obligation.cause.clone(), - obligation.param_env.clone(), + obligation.param_env, normalized_bound, )); } diff --git a/compiler/rustc_trait_selection/src/traits/select/mod.rs b/compiler/rustc_trait_selection/src/traits/select/mod.rs index 05ff9a6fb9c..74b6652981a 100644 --- a/compiler/rustc_trait_selection/src/traits/select/mod.rs +++ b/compiler/rustc_trait_selection/src/traits/select/mod.rs @@ -31,6 +31,7 @@ use rustc_data_structures::stack::ensure_sufficient_stack; use rustc_errors::ErrorReported; use rustc_hir as hir; use rustc_hir::def_id::DefId; +use rustc_hir::Constness; use rustc_middle::dep_graph::{DepKind, DepNodeIndex}; use rustc_middle::mir::interpret::ErrorHandled; use rustc_middle::ty::fast_reject; @@ -832,11 +833,10 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { /// - it also appears in the backtrace at some position `X`, /// - all the predicates at positions `X..` between `X` and the top are /// also defaulted traits. - pub fn coinductive_match<I>(&mut self, cycle: I) -> bool + pub fn coinductive_match<I>(&mut self, mut cycle: I) -> bool where I: Iterator<Item = ty::Predicate<'tcx>>, { - let mut cycle = cycle; cycle.all(|predicate| self.coinductive_predicate(predicate)) } @@ -1335,7 +1335,14 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { (BuiltinCandidate { has_nested: false } | DiscriminantKindCandidate, _) => true, (_, BuiltinCandidate { has_nested: false } | DiscriminantKindCandidate) => false, - (ParamCandidate(..), ParamCandidate(..)) => false, + (ParamCandidate(other), ParamCandidate(victim)) => { + if other.value == victim.value && victim.constness == Constness::NotConst { + // Drop otherwise equivalent non-const candidates in favor of const candidates. + true + } else { + false + } + } // Global bounds from the where clause should be ignored // here (see issue #50825). Otherwise, we have a where @@ -1354,11 +1361,11 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { | TraitAliasCandidate(..) | ObjectCandidate(_) | ProjectionCandidate(_), - ) => !is_global(cand), + ) => !is_global(&cand.value), (ObjectCandidate(_) | ProjectionCandidate(_), ParamCandidate(ref cand)) => { // Prefer these to a global where-clause bound // (see issue #50825). - is_global(cand) + is_global(&cand.value) } ( ImplCandidate(_) @@ -1373,7 +1380,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { ) => { // Prefer these to a global where-clause bound // (see issue #50825). - is_global(cand) && other.evaluation.must_apply_modulo_regions() + is_global(&cand.value) && other.evaluation.must_apply_modulo_regions() } (ProjectionCandidate(i), ProjectionCandidate(j)) @@ -2364,13 +2371,9 @@ impl<'o, 'tcx> Iterator for TraitObligationStackList<'o, 'tcx> { type Item = &'o TraitObligationStack<'o, 'tcx>; fn next(&mut self) -> Option<&'o TraitObligationStack<'o, 'tcx>> { - match self.head { - Some(o) => { - *self = o.previous; - Some(o) - } - None => None, - } + let o = self.head?; + *self = o.previous; + Some(o) } } diff --git a/compiler/rustc_trait_selection/src/traits/specialize/mod.rs b/compiler/rustc_trait_selection/src/traits/specialize/mod.rs index 512591960f5..0133a961c11 100644 --- a/compiler/rustc_trait_selection/src/traits/specialize/mod.rs +++ b/compiler/rustc_trait_selection/src/traits/specialize/mod.rs @@ -498,8 +498,8 @@ fn to_pretty_impl_header(tcx: TyCtxt<'_>, impl_def_id: DefId) -> Option<String> for (p, _) in predicates { if let Some(poly_trait_ref) = p.to_opt_poly_trait_ref() { - if Some(poly_trait_ref.def_id()) == sized_trait { - types_without_default_bounds.remove(poly_trait_ref.self_ty().skip_binder()); + if Some(poly_trait_ref.value.def_id()) == sized_trait { + types_without_default_bounds.remove(poly_trait_ref.value.self_ty().skip_binder()); continue; } } diff --git a/compiler/rustc_trait_selection/src/traits/util.rs b/compiler/rustc_trait_selection/src/traits/util.rs index 2430620323f..ab4a81c7d15 100644 --- a/compiler/rustc_trait_selection/src/traits/util.rs +++ b/compiler/rustc_trait_selection/src/traits/util.rs @@ -125,7 +125,7 @@ impl<'tcx> TraitAliasExpander<'tcx> { let items = predicates.predicates.iter().rev().filter_map(|(pred, span)| { pred.subst_supertrait(tcx, &trait_ref) .to_opt_poly_trait_ref() - .map(|trait_ref| item.clone_and_push(trait_ref, *span)) + .map(|trait_ref| item.clone_and_push(trait_ref.value, *span)) }); debug!("expand_trait_aliases: items={:?}", items.clone()); @@ -182,7 +182,7 @@ impl Iterator for SupertraitDefIds<'tcx> { .predicates .iter() .filter_map(|(pred, _)| pred.to_opt_poly_trait_ref()) - .map(|trait_ref| trait_ref.def_id()) + .map(|trait_ref| trait_ref.value.def_id()) .filter(|&super_def_id| visited.insert(super_def_id)), ); Some(def_id) diff --git a/compiler/rustc_trait_selection/src/traits/wf.rs b/compiler/rustc_trait_selection/src/traits/wf.rs index e5a792f229d..5bcb16d21e0 100644 --- a/compiler/rustc_trait_selection/src/traits/wf.rs +++ b/compiler/rustc_trait_selection/src/traits/wf.rs @@ -294,7 +294,7 @@ impl<'a, 'tcx> WfPredicates<'a, 'tcx> { let mut cause = cause.clone(); if let Some(parent_trait_ref) = obligation.predicate.to_opt_poly_trait_ref() { let derived_cause = traits::DerivedObligationCause { - parent_trait_ref, + parent_trait_ref: parent_trait_ref.value, parent_code: Rc::new(obligation.cause.code.clone()), }; cause.make_mut().code = |
