From 1c4fe64bdcb0cc27c91c5405430f0ca189fcd065 Mon Sep 17 00:00:00 2001 From: kadmin Date: Thu, 27 Jan 2022 14:40:38 +0000 Subject: [PATCH 1/4] Continue work on assoc const eq --- compiler/rustc_middle/src/ty/mod.rs | 3 + .../src/traits/project.rs | 475 ++++++++++++++---- compiler/rustc_typeck/src/astconv/mod.rs | 35 +- compiler/rustc_typeck/src/collect/type_of.rs | 85 +++- src/test/ui/associated-consts/assoc-const.rs | 11 +- .../ui/associated-consts/assoc-const.stderr | 14 - 6 files changed, 471 insertions(+), 152 deletions(-) delete mode 100644 src/test/ui/associated-consts/assoc-const.stderr diff --git a/compiler/rustc_middle/src/ty/mod.rs b/compiler/rustc_middle/src/ty/mod.rs index 6174c922e2d06..05a210ef49edf 100644 --- a/compiler/rustc_middle/src/ty/mod.rs +++ b/compiler/rustc_middle/src/ty/mod.rs @@ -857,6 +857,9 @@ impl<'tcx> Term<'tcx> { pub fn ty(&self) -> Option> { if let Term::Ty(ty) = self { Some(ty) } else { None } } + pub fn ct(&self) -> Option<&'tcx Const<'tcx>> { + if let Term::Const(c) = self { Some(c) } else { None } + } } /// This kind of predicate has no *direct* correspondent in the diff --git a/compiler/rustc_trait_selection/src/traits/project.rs b/compiler/rustc_trait_selection/src/traits/project.rs index e8b46e88a4228..8f498f02169f2 100644 --- a/compiler/rustc_trait_selection/src/traits/project.rs +++ b/compiler/rustc_trait_selection/src/traits/project.rs @@ -44,7 +44,7 @@ pub(super) struct InProgress; /// When attempting to resolve `::Name` ... #[derive(Debug)] -pub enum ProjectionTyError<'tcx> { +pub enum ProjectionError<'tcx> { /// ...we found multiple sources of information and couldn't resolve the ambiguity. TooManyCandidates, @@ -53,7 +53,7 @@ pub enum ProjectionTyError<'tcx> { } #[derive(PartialEq, Eq, Debug)] -enum ProjectionTyCandidate<'tcx> { +enum ProjectionCandidate<'tcx> { /// From a where-clause in the env or object type ParamEnv(ty::PolyProjectionPredicate<'tcx>), @@ -67,28 +67,28 @@ enum ProjectionTyCandidate<'tcx> { Select(Selection<'tcx>), } -enum ProjectionTyCandidateSet<'tcx> { +enum ProjectionCandidateSet<'tcx> { None, - Single(ProjectionTyCandidate<'tcx>), + Single(ProjectionCandidate<'tcx>), Ambiguous, Error(SelectionError<'tcx>), } -impl<'tcx> ProjectionTyCandidateSet<'tcx> { +impl<'tcx> ProjectionCandidateSet<'tcx> { fn mark_ambiguous(&mut self) { - *self = ProjectionTyCandidateSet::Ambiguous; + *self = ProjectionCandidateSet::Ambiguous; } fn mark_error(&mut self, err: SelectionError<'tcx>) { - *self = ProjectionTyCandidateSet::Error(err); + *self = ProjectionCandidateSet::Error(err); } // Returns true if the push was successful, or false if the candidate // was discarded -- this could be because of ambiguity, or because // a higher-priority candidate is already there. - fn push_candidate(&mut self, candidate: ProjectionTyCandidate<'tcx>) -> bool { - use self::ProjectionTyCandidate::*; - use self::ProjectionTyCandidateSet::*; + fn push_candidate(&mut self, candidate: ProjectionCandidate<'tcx>) -> bool { + use self::ProjectionCandidate::*; + use self::ProjectionCandidateSet::*; // This wacky variable is just used to try and // make code readable and avoid confusing paths. @@ -196,32 +196,67 @@ fn project_and_unify_type<'cx, 'tcx>( debug!(?obligation, "project_and_unify_type"); let mut obligations = vec![]; - let normalized_ty = match opt_normalize_projection_type( - selcx, - obligation.param_env, - obligation.predicate.projection_ty, - obligation.cause.clone(), - obligation.recursion_depth, - &mut obligations, - ) { - Ok(Some(n)) => n, - Ok(None) => return Ok(Ok(None)), - Err(InProgress) => return Ok(Err(InProgress)), - }; - - debug!(?normalized_ty, ?obligations, "project_and_unify_type result"); let infcx = selcx.infcx(); - // FIXME(associated_const_equality): Handle consts here as well as types. - let obligation_pred_ty = obligation.predicate.term.ty().unwrap(); - match infcx.at(&obligation.cause, obligation.param_env).eq(normalized_ty, obligation_pred_ty) { - Ok(InferOk { obligations: inferred_obligations, value: () }) => { - obligations.extend(inferred_obligations); - Ok(Ok(Some(obligations))) + match obligation.predicate.term { + ty::Term::Ty(obligation_pred_ty) => { + let normalized_ty = match opt_normalize_projection_type( + selcx, + obligation.param_env, + obligation.predicate.projection_ty, + obligation.cause.clone(), + obligation.recursion_depth, + &mut obligations, + ) { + Ok(Some(n)) => n, + Ok(None) => return Ok(Ok(None)), + Err(InProgress) => return Ok(Err(InProgress)), + }; + debug!(?normalized_ty, ?obligations, "project_and_unify_type result"); + match infcx + .at(&obligation.cause, obligation.param_env) + .eq(normalized_ty, obligation_pred_ty) + { + Ok(InferOk { obligations: inferred_obligations, value: () }) => { + obligations.extend(inferred_obligations); + Ok(Ok(Some(obligations))) + } + Err(err) => { + debug!("project_and_unify_type: equating types encountered error {:?}", err); + Err(MismatchedProjectionTypes { err }) + } + } } - Err(err) => { - debug!("project_and_unify_type: equating types encountered error {:?}", err); - Err(MismatchedProjectionTypes { err }) + ty::Term::Const(_obligation_pred_const) => { + let normalized_const = match opt_normalize_projection_const( + selcx, + obligation.param_env, + obligation.predicate.projection_ty, + obligation.cause.clone(), + obligation.recursion_depth, + &mut obligations, + ) { + Ok(Some(n)) => n, + Ok(None) => return Ok(Ok(None)), + Err(InProgress) => return Ok(Err(InProgress)), + }; + println!("{:?}", normalized_const); + todo!(); + /* + match infcx + .at(&obligation.cause, obligation.param_env) + .eq(normalized_ty, obligation_pred_const) + { + Ok(InferOk { obligations: inferred_obligations, value: () }) => { + obligations.extend(inferred_obligations); + Ok(Ok(Some(obligations))) + } + Err(err) => { + debug!("project_and_unify_type: equating consts encountered error {:?}", err); + Err(MismatchedProjectionTypes { err }) + } + } + */ } } } @@ -813,6 +848,22 @@ pub fn normalize_projection_type<'a, 'b, 'tcx>( }) } +fn opt_normalize_projection_const<'a, 'b, 'tcx>( + selcx: &'a mut SelectionContext<'b, 'tcx>, + param_env: ty::ParamEnv<'tcx>, + projection_const: ty::ProjectionTy<'tcx>, + cause: ObligationCause<'tcx>, + depth: usize, + _obligations: &mut Vec>, +) -> Result>, InProgress> { + let infcx = selcx.infcx(); + let projection_const = infcx.resolve_vars_if_possible(projection_const); + let obligation = Obligation::with_depth(cause.clone(), depth, param_env, projection_const); + // TODO continue working on below + let _projected_const = project_const(selcx, &obligation); + //println!("{:?}", projected_const); + todo!(); +} /// The guts of `normalize`: normalize a specific projection like `::Item`. The result is always a type (and possibly /// additional obligations). Returns `None` in the case of ambiguity, @@ -914,8 +965,8 @@ fn opt_normalize_projection_type<'a, 'b, 'tcx>( let obligation = Obligation::with_depth(cause.clone(), depth, param_env, projection_ty); match project_type(selcx, &obligation) { - Ok(ProjectedTy::Progress(Progress { - ty: projected_ty, + Ok(Projected::Progress(Progress { + term: projected_ty, obligations: mut projected_obligations, })) => { // if projection succeeded, then what we get out of this @@ -957,7 +1008,7 @@ fn opt_normalize_projection_type<'a, 'b, 'tcx>( obligations.extend(result.obligations); Ok(Some(result.value)) } - Ok(ProjectedTy::NoProgress(projected_ty)) => { + Ok(Projected::NoProgress(projected_ty)) => { debug!(?projected_ty, "opt_normalize_projection_type: no progress"); let result = Normalized { value: projected_ty, obligations: vec![] }; if use_cache { @@ -966,14 +1017,14 @@ fn opt_normalize_projection_type<'a, 'b, 'tcx>( // No need to extend `obligations`. Ok(Some(result.value)) } - Err(ProjectionTyError::TooManyCandidates) => { + Err(ProjectionError::TooManyCandidates) => { debug!("opt_normalize_projection_type: too many candidates"); if use_cache { infcx.inner.borrow_mut().projection_cache().ambiguous(cache_key); } Ok(None) } - Err(ProjectionTyError::TraitSelectionError(_)) => { + Err(ProjectionError::TraitSelectionError(_)) => { debug!("opt_normalize_projection_type: ERROR"); // if we got an error processing the `T as Trait` part, // just return `ty::err` but add the obligation `T : @@ -1032,35 +1083,76 @@ fn normalize_to_error<'a, 'tcx>( Normalized { value: new_value, obligations: vec![trait_obligation] } } -enum ProjectedTy<'tcx> { - Progress(Progress<'tcx>), - NoProgress(Ty<'tcx>), +enum Projected<'tcx, T> { + Progress(Progress<'tcx, T>), + NoProgress(T), } -struct Progress<'tcx> { - ty: Ty<'tcx>, +struct Progress<'tcx, T> +where + T: 'tcx, +{ + term: T, obligations: Vec>, } -impl<'tcx> Progress<'tcx> { +impl<'tcx> Progress<'tcx, Ty<'tcx>> { fn error(tcx: TyCtxt<'tcx>) -> Self { - Progress { ty: tcx.ty_error(), obligations: vec![] } + Progress { term: tcx.ty_error(), obligations: vec![] } } fn with_addl_obligations(mut self, mut obligations: Vec>) -> Self { - debug!( - self.obligations.len = ?self.obligations.len(), - obligations.len = obligations.len(), - "with_addl_obligations" - ); - - debug!(?self.obligations, ?obligations, "with_addl_obligations"); - self.obligations.append(&mut obligations); self } } +impl<'tcx> Progress<'tcx, &'tcx ty::Const<'tcx>> { + fn error_const(tcx: TyCtxt<'tcx>) -> Self { + Progress { term: tcx.const_error(tcx.ty_error()), obligations: vec![] } + } +} + +fn project_const<'cx, 'tcx>( + selcx: &mut SelectionContext<'cx, 'tcx>, + obligation: &ProjectionTyObligation<'tcx>, +) -> Result>, ProjectionError<'tcx>> { + if !selcx.tcx().recursion_limit().value_within_limit(obligation.recursion_depth) { + return Err(ProjectionError::TraitSelectionError(SelectionError::Overflow)); + } + + if obligation.predicate.references_error() { + return Ok(Projected::Progress(Progress::error_const(selcx.tcx()))); + } + + let mut candidates = ProjectionCandidateSet::None; + + assemble_candidates_from_param_env(selcx, obligation, &mut candidates); + assemble_candidates_from_trait_def(selcx, obligation, &mut candidates); + assemble_candidates_from_object_ty(selcx, obligation, &mut candidates); + if let ProjectionCandidateSet::Single(ProjectionCandidate::Object(_)) = candidates { + } else { + assemble_candidates_from_impls(selcx, obligation, &mut candidates); + }; + match candidates { + ProjectionCandidateSet::Single(candidate) => { + Ok(Projected::Progress(confirm_candidate_const(selcx, obligation, candidate))) + } + ProjectionCandidateSet::None => todo!(), + /* + Ok(Projected::NoProgress( + selcx + .tcx() + .mk_projection(obligation.predicate.item_def_id, obligation.predicate.substs), + )), + */ + // Error occurred while trying to processing impls. + ProjectionCandidateSet::Error(e) => Err(ProjectionError::TraitSelectionError(e)), + // Inherent ambiguity that prevents us from even enumerating the candidates. + ProjectionCandidateSet::Ambiguous => Err(ProjectionError::TooManyCandidates), + } +} + /// Computes the result of a projection type (if we can). /// /// IMPORTANT: @@ -1069,19 +1161,18 @@ impl<'tcx> Progress<'tcx> { fn project_type<'cx, 'tcx>( selcx: &mut SelectionContext<'cx, 'tcx>, obligation: &ProjectionTyObligation<'tcx>, -) -> Result, ProjectionTyError<'tcx>> { +) -> Result>, ProjectionError<'tcx>> { if !selcx.tcx().recursion_limit().value_within_limit(obligation.recursion_depth) { - debug!("project: overflow!"); // This should really be an immediate error, but some existing code // relies on being able to recover from this. - return Err(ProjectionTyError::TraitSelectionError(SelectionError::Overflow)); + return Err(ProjectionError::TraitSelectionError(SelectionError::Overflow)); } if obligation.predicate.references_error() { - return Ok(ProjectedTy::Progress(Progress::error(selcx.tcx()))); + return Ok(Projected::Progress(Progress::error(selcx.tcx()))); } - let mut candidates = ProjectionTyCandidateSet::None; + let mut candidates = ProjectionCandidateSet::None; // Make sure that the following procedures are kept in order. ParamEnv // needs to be first because it has highest priority, and Select checks @@ -1092,7 +1183,7 @@ fn project_type<'cx, 'tcx>( assemble_candidates_from_object_ty(selcx, obligation, &mut candidates); - if let ProjectionTyCandidateSet::Single(ProjectionTyCandidate::Object(_)) = candidates { + if let ProjectionCandidateSet::Single(ProjectionCandidate::Object(_)) = candidates { // Avoid normalization cycle from selection (see // `assemble_candidates_from_object_ty`). // FIXME(lazy_normalization): Lazy normalization should save us from @@ -1102,19 +1193,19 @@ fn project_type<'cx, 'tcx>( }; match candidates { - ProjectionTyCandidateSet::Single(candidate) => { - Ok(ProjectedTy::Progress(confirm_candidate(selcx, obligation, candidate))) + ProjectionCandidateSet::Single(candidate) => { + Ok(Projected::Progress(confirm_candidate(selcx, obligation, candidate))) } - ProjectionTyCandidateSet::None => Ok(ProjectedTy::NoProgress( + ProjectionCandidateSet::None => Ok(Projected::NoProgress( selcx .tcx() .mk_projection(obligation.predicate.item_def_id, obligation.predicate.substs), )), // Error occurred while trying to processing impls. - ProjectionTyCandidateSet::Error(e) => Err(ProjectionTyError::TraitSelectionError(e)), + ProjectionCandidateSet::Error(e) => Err(ProjectionError::TraitSelectionError(e)), // Inherent ambiguity that prevents us from even enumerating the // candidates. - ProjectionTyCandidateSet::Ambiguous => Err(ProjectionTyError::TooManyCandidates), + ProjectionCandidateSet::Ambiguous => Err(ProjectionError::TooManyCandidates), } } @@ -1124,14 +1215,13 @@ fn project_type<'cx, 'tcx>( fn assemble_candidates_from_param_env<'cx, 'tcx>( selcx: &mut SelectionContext<'cx, 'tcx>, obligation: &ProjectionTyObligation<'tcx>, - candidate_set: &mut ProjectionTyCandidateSet<'tcx>, + candidate_set: &mut ProjectionCandidateSet<'tcx>, ) { - debug!("assemble_candidates_from_param_env(..)"); assemble_candidates_from_predicates( selcx, obligation, candidate_set, - ProjectionTyCandidate::ParamEnv, + ProjectionCandidate::ParamEnv, obligation.param_env.caller_bounds().iter(), false, ); @@ -1150,7 +1240,7 @@ fn assemble_candidates_from_param_env<'cx, 'tcx>( fn assemble_candidates_from_trait_def<'cx, 'tcx>( selcx: &mut SelectionContext<'cx, 'tcx>, obligation: &ProjectionTyObligation<'tcx>, - candidate_set: &mut ProjectionTyCandidateSet<'tcx>, + candidate_set: &mut ProjectionCandidateSet<'tcx>, ) { debug!("assemble_candidates_from_trait_def(..)"); @@ -1173,7 +1263,7 @@ fn assemble_candidates_from_trait_def<'cx, 'tcx>( selcx, obligation, candidate_set, - ProjectionTyCandidate::TraitDef, + ProjectionCandidate::TraitDef, bounds.iter(), true, ) @@ -1191,7 +1281,7 @@ fn assemble_candidates_from_trait_def<'cx, 'tcx>( fn assemble_candidates_from_object_ty<'cx, 'tcx>( selcx: &mut SelectionContext<'cx, 'tcx>, obligation: &ProjectionTyObligation<'tcx>, - candidate_set: &mut ProjectionTyCandidateSet<'tcx>, + candidate_set: &mut ProjectionCandidateSet<'tcx>, ) { debug!("assemble_candidates_from_object_ty(..)"); @@ -1218,7 +1308,7 @@ fn assemble_candidates_from_object_ty<'cx, 'tcx>( selcx, obligation, candidate_set, - ProjectionTyCandidate::Object, + ProjectionCandidate::Object, env_predicates, false, ); @@ -1231,14 +1321,13 @@ fn assemble_candidates_from_object_ty<'cx, 'tcx>( fn assemble_candidates_from_predicates<'cx, 'tcx>( selcx: &mut SelectionContext<'cx, 'tcx>, obligation: &ProjectionTyObligation<'tcx>, - candidate_set: &mut ProjectionTyCandidateSet<'tcx>, - ctor: fn(ty::PolyProjectionPredicate<'tcx>) -> ProjectionTyCandidate<'tcx>, + candidate_set: &mut ProjectionCandidateSet<'tcx>, + ctor: fn(ty::PolyProjectionPredicate<'tcx>) -> ProjectionCandidate<'tcx>, env_predicates: impl Iterator>, potentially_unnormalized_candidates: bool, ) { let infcx = selcx.infcx(); for predicate in env_predicates { - debug!(?predicate); let bound_predicate = predicate.kind(); if let ty::PredicateKind::Projection(data) = predicate.kind().skip_binder() { let data = bound_predicate.rebind(data); @@ -1253,8 +1342,6 @@ fn assemble_candidates_from_predicates<'cx, 'tcx>( ) }); - debug!(?data, ?is_match, ?same_def_id); - if is_match { candidate_set.push_candidate(ctor(data)); @@ -1275,7 +1362,7 @@ fn assemble_candidates_from_predicates<'cx, 'tcx>( fn assemble_candidates_from_impls<'cx, 'tcx>( selcx: &mut SelectionContext<'cx, 'tcx>, obligation: &ProjectionTyObligation<'tcx>, - candidate_set: &mut ProjectionTyCandidateSet<'tcx>, + candidate_set: &mut ProjectionCandidateSet<'tcx>, ) { // If we are resolving `>::Item == Type`, // start out by selecting the predicate `T as TraitRef<...>`: @@ -1327,7 +1414,7 @@ fn assemble_candidates_from_impls<'cx, 'tcx>( // NOTE: This should be kept in sync with the similar code in // `rustc_ty_utils::instance::resolve_associated_item()`. let node_item = - assoc_ty_def(selcx, impl_data.impl_def_id, obligation.predicate.item_def_id) + assoc_def(selcx, impl_data.impl_def_id, obligation.predicate.item_def_id) .map_err(|ErrorReported| ())?; if node_item.is_final() { @@ -1500,7 +1587,7 @@ fn assemble_candidates_from_impls<'cx, 'tcx>( }; if eligible { - if candidate_set.push_candidate(ProjectionTyCandidate::Select(impl_source)) { + if candidate_set.push_candidate(ProjectionCandidate::Select(impl_source)) { Ok(()) } else { Err(()) @@ -1514,30 +1601,62 @@ fn assemble_candidates_from_impls<'cx, 'tcx>( fn confirm_candidate<'cx, 'tcx>( selcx: &mut SelectionContext<'cx, 'tcx>, obligation: &ProjectionTyObligation<'tcx>, - candidate: ProjectionTyCandidate<'tcx>, -) -> Progress<'tcx> { + candidate: ProjectionCandidate<'tcx>, +) -> Progress<'tcx, Ty<'tcx>> { debug!(?obligation, ?candidate, "confirm_candidate"); let mut progress = match candidate { - ProjectionTyCandidate::ParamEnv(poly_projection) - | ProjectionTyCandidate::Object(poly_projection) => { + ProjectionCandidate::ParamEnv(poly_projection) + | ProjectionCandidate::Object(poly_projection) => { confirm_param_env_candidate(selcx, obligation, poly_projection, false) } - ProjectionTyCandidate::TraitDef(poly_projection) => { + ProjectionCandidate::TraitDef(poly_projection) => { confirm_param_env_candidate(selcx, obligation, poly_projection, true) } - ProjectionTyCandidate::Select(impl_source) => { + ProjectionCandidate::Select(impl_source) => { confirm_select_candidate(selcx, obligation, impl_source) } }; + + // When checking for cycle during evaluation, we compare predicates with + // "syntactic" equality. Since normalization generally introduces a type + // with new region variables, we need to resolve them to existing variables + // when possible for this to work. See `auto-trait-projection-recursion.rs` + // for a case where this matters. + if progress.term.has_infer_regions() { + progress.term = OpportunisticRegionResolver::new(selcx.infcx()).fold_ty(progress.term); + } + progress +} + +fn confirm_candidate_const<'cx, 'tcx>( + selcx: &mut SelectionContext<'cx, 'tcx>, + obligation: &ProjectionTyObligation<'tcx>, + candidate: ProjectionCandidate<'tcx>, +) -> Progress<'tcx, &'tcx ty::Const<'tcx>> { + let mut progress = match candidate { + ProjectionCandidate::ParamEnv(poly_projection) + | ProjectionCandidate::Object(poly_projection) => { + confirm_param_env_candidate_const(selcx, obligation, poly_projection, false) + } + + ProjectionCandidate::TraitDef(poly_projection) => { + confirm_param_env_candidate_const(selcx, obligation, poly_projection, true) + } + + ProjectionCandidate::Select(impl_source) => { + confirm_select_candidate_const(selcx, obligation, impl_source) + } + }; + // When checking for cycle during evaluation, we compare predicates with // "syntactic" equality. Since normalization generally introduces a type // with new region variables, we need to resolve them to existing variables // when possible for this to work. See `auto-trait-projection-recursion.rs` // for a case where this matters. - if progress.ty.has_infer_regions() { - progress.ty = OpportunisticRegionResolver::new(selcx.infcx()).fold_ty(progress.ty); + if progress.term.has_infer_regions() { + progress.term = OpportunisticRegionResolver::new(selcx.infcx()).fold_const(progress.term); } progress } @@ -1546,7 +1665,7 @@ fn confirm_select_candidate<'cx, 'tcx>( selcx: &mut SelectionContext<'cx, 'tcx>, obligation: &ProjectionTyObligation<'tcx>, impl_source: Selection<'tcx>, -) -> Progress<'tcx> { +) -> Progress<'tcx, Ty<'tcx>> { match impl_source { super::ImplSource::UserDefined(data) => confirm_impl_candidate(selcx, obligation, data), super::ImplSource::Generator(data) => confirm_generator_candidate(selcx, obligation, data), @@ -1573,11 +1692,42 @@ fn confirm_select_candidate<'cx, 'tcx>( } } +fn confirm_select_candidate_const<'cx, 'tcx>( + selcx: &mut SelectionContext<'cx, 'tcx>, + obligation: &ProjectionTyObligation<'tcx>, + impl_source: Selection<'tcx>, +) -> Progress<'tcx, &'tcx ty::Const<'tcx>> { + match impl_source { + super::ImplSource::UserDefined(data) => { + confirm_impl_candidate_const(selcx, obligation, data) + } + super::ImplSource::Generator(_) + | super::ImplSource::Closure(_) + | super::ImplSource::FnPointer(_) + | super::ImplSource::DiscriminantKind(_) + | super::ImplSource::Pointee(_) => todo!(), + super::ImplSource::Object(_) + | super::ImplSource::AutoImpl(..) + | super::ImplSource::Param(..) + | super::ImplSource::Builtin(..) + | super::ImplSource::TraitUpcasting(_) + | super::ImplSource::TraitAlias(..) + | super::ImplSource::ConstDrop(_) => { + // we don't create Select candidates with this kind of resolution + span_bug!( + obligation.cause.span, + "Cannot project an associated type from `{:?}`", + impl_source + ) + } + } +} + fn confirm_generator_candidate<'cx, 'tcx>( selcx: &mut SelectionContext<'cx, 'tcx>, obligation: &ProjectionTyObligation<'tcx>, impl_source: ImplSourceGeneratorData<'tcx, PredicateObligation<'tcx>>, -) -> Progress<'tcx> { +) -> Progress<'tcx, Ty<'tcx>> { let gen_sig = impl_source.substs.as_generator().poly_sig(); let Normalized { value: gen_sig, obligations } = normalize_with_depth( selcx, @@ -1627,7 +1777,7 @@ fn confirm_discriminant_kind_candidate<'cx, 'tcx>( selcx: &mut SelectionContext<'cx, 'tcx>, obligation: &ProjectionTyObligation<'tcx>, _: ImplSourceDiscriminantKindData, -) -> Progress<'tcx> { +) -> Progress<'tcx, Ty<'tcx>> { let tcx = selcx.tcx(); let self_ty = selcx.infcx().shallow_resolve(obligation.predicate.self_ty()); @@ -1652,7 +1802,7 @@ fn confirm_pointee_candidate<'cx, 'tcx>( selcx: &mut SelectionContext<'cx, 'tcx>, obligation: &ProjectionTyObligation<'tcx>, _: ImplSourcePointeeData, -) -> Progress<'tcx> { +) -> Progress<'tcx, Ty<'tcx>> { let tcx = selcx.tcx(); let self_ty = selcx.infcx().shallow_resolve(obligation.predicate.self_ty()); @@ -1684,7 +1834,7 @@ fn confirm_fn_pointer_candidate<'cx, 'tcx>( selcx: &mut SelectionContext<'cx, 'tcx>, obligation: &ProjectionTyObligation<'tcx>, fn_pointer_impl_source: ImplSourceFnPointerData<'tcx, PredicateObligation<'tcx>>, -) -> Progress<'tcx> { +) -> Progress<'tcx, Ty<'tcx>> { let fn_type = selcx.infcx().shallow_resolve(fn_pointer_impl_source.fn_ty); let sig = fn_type.fn_sig(selcx.tcx()); let Normalized { value: sig, obligations } = normalize_with_depth( @@ -1704,7 +1854,7 @@ fn confirm_closure_candidate<'cx, 'tcx>( selcx: &mut SelectionContext<'cx, 'tcx>, obligation: &ProjectionTyObligation<'tcx>, impl_source: ImplSourceClosureData<'tcx, PredicateObligation<'tcx>>, -) -> Progress<'tcx> { +) -> Progress<'tcx, Ty<'tcx>> { let closure_sig = impl_source.substs.as_closure().sig(); let Normalized { value: closure_sig, obligations } = normalize_with_depth( selcx, @@ -1726,7 +1876,7 @@ fn confirm_callable_candidate<'cx, 'tcx>( obligation: &ProjectionTyObligation<'tcx>, fn_sig: ty::PolyFnSig<'tcx>, flag: util::TupleArgumentsFlag, -) -> Progress<'tcx> { +) -> Progress<'tcx, Ty<'tcx>> { let tcx = selcx.tcx(); debug!(?obligation, ?fn_sig, "confirm_callable_candidate"); @@ -1757,7 +1907,7 @@ fn confirm_param_env_candidate<'cx, 'tcx>( obligation: &ProjectionTyObligation<'tcx>, poly_cache_entry: ty::PolyProjectionPredicate<'tcx>, potentially_unnormalized_candidate: bool, -) -> Progress<'tcx> { +) -> Progress<'tcx, Ty<'tcx>> { let infcx = selcx.infcx(); let cause = &obligation.cause; let param_env = obligation.param_env; @@ -1804,7 +1954,7 @@ fn confirm_param_env_candidate<'cx, 'tcx>( assoc_ty_own_obligations(selcx, obligation, &mut nested_obligations); // FIXME(associated_const_equality): Handle consts here as well? Maybe this progress type should just take // a term instead. - Progress { ty: cache_entry.term.ty().unwrap(), obligations: nested_obligations } + Progress { term: cache_entry.term.ty().unwrap(), obligations: nested_obligations } } Err(e) => { let msg = format!( @@ -1813,7 +1963,72 @@ fn confirm_param_env_candidate<'cx, 'tcx>( ); debug!("confirm_param_env_candidate: {}", msg); let err = infcx.tcx.ty_error_with_message(obligation.cause.span, &msg); - Progress { ty: err, obligations: vec![] } + Progress { term: err, obligations: vec![] } + } + } +} + +fn confirm_param_env_candidate_const<'cx, 'tcx>( + selcx: &mut SelectionContext<'cx, 'tcx>, + obligation: &ProjectionTyObligation<'tcx>, + poly_cache_entry: ty::PolyProjectionPredicate<'tcx>, + potentially_unnormalized_candidate: bool, +) -> Progress<'tcx, &'tcx ty::Const<'tcx>> { + let infcx = selcx.infcx(); + let cause = &obligation.cause; + let param_env = obligation.param_env; + + let (cache_entry, _) = infcx.replace_bound_vars_with_fresh_vars( + cause.span, + LateBoundRegionConversionTime::HigherRankedType, + poly_cache_entry, + ); + + let cache_projection = cache_entry.projection_ty; + let mut nested_obligations = Vec::new(); + let obligation_projection = obligation.predicate; + let obligation_projection = ensure_sufficient_stack(|| { + normalize_with_depth_to( + selcx, + obligation.param_env, + obligation.cause.clone(), + obligation.recursion_depth + 1, + obligation_projection, + &mut nested_obligations, + ) + }); + let cache_projection = if potentially_unnormalized_candidate { + ensure_sufficient_stack(|| { + normalize_with_depth_to( + selcx, + obligation.param_env, + obligation.cause.clone(), + obligation.recursion_depth + 1, + cache_projection, + &mut nested_obligations, + ) + }) + } else { + cache_projection + }; + + match infcx.at(cause, param_env).eq(cache_projection, obligation_projection) { + Ok(InferOk { value: _, obligations }) => { + nested_obligations.extend(obligations); + assoc_ty_own_obligations(selcx, obligation, &mut nested_obligations); + Progress { term: cache_entry.term.ct().unwrap(), obligations: nested_obligations } + } + Err(e) => { + let msg = format!( + "Failed to unify obligation `{:?}` with poly_projection `{:?}`: {:?}", + obligation, poly_cache_entry, e, + ); + let err = infcx.tcx.const_error_with_message( + infcx.tcx.ty_error(), + obligation.cause.span, + &msg, + ); + Progress { term: err, obligations: vec![] } } } } @@ -1822,7 +2037,7 @@ fn confirm_impl_candidate<'cx, 'tcx>( selcx: &mut SelectionContext<'cx, 'tcx>, obligation: &ProjectionTyObligation<'tcx>, impl_impl_source: ImplSourceUserDefinedData<'tcx, PredicateObligation<'tcx>>, -) -> Progress<'tcx> { +) -> Progress<'tcx, Ty<'tcx>> { let tcx = selcx.tcx(); let ImplSourceUserDefinedData { impl_def_id, substs, mut nested } = impl_impl_source; @@ -1830,9 +2045,9 @@ fn confirm_impl_candidate<'cx, 'tcx>( let trait_def_id = tcx.trait_id_of_impl(impl_def_id).unwrap(); let param_env = obligation.param_env; - let assoc_ty = match assoc_ty_def(selcx, impl_def_id, assoc_item_id) { + let assoc_ty = match assoc_def(selcx, impl_def_id, assoc_item_id) { Ok(assoc_ty) => assoc_ty, - Err(ErrorReported) => return Progress { ty: tcx.ty_error(), obligations: nested }, + Err(ErrorReported) => return Progress { term: tcx.ty_error(), obligations: nested }, }; if !assoc_ty.item.defaultness.has_value() { @@ -1844,7 +2059,7 @@ fn confirm_impl_candidate<'cx, 'tcx>( "confirm_impl_candidate: no associated type {:?} for {:?}", assoc_ty.item.name, obligation.predicate ); - return Progress { ty: tcx.ty_error(), obligations: nested }; + return Progress { term: tcx.ty_error(), obligations: nested }; } // If we're trying to normalize ` as X>::A` using //`impl X for Vec { type A = Box; }`, then: @@ -1861,10 +2076,54 @@ fn confirm_impl_candidate<'cx, 'tcx>( obligation.cause.span, "impl item and trait item have different parameter counts", ); - Progress { ty: err, obligations: nested } + Progress { term: err, obligations: nested } } else { assoc_ty_own_obligations(selcx, obligation, &mut nested); - Progress { ty: ty.subst(tcx, substs), obligations: nested } + Progress { term: ty.subst(tcx, substs), obligations: nested } + } +} + +fn confirm_impl_candidate_const<'cx, 'tcx>( + selcx: &mut SelectionContext<'cx, 'tcx>, + obligation: &ProjectionTyObligation<'tcx>, + impl_impl_source: ImplSourceUserDefinedData<'tcx, PredicateObligation<'tcx>>, +) -> Progress<'tcx, &'tcx ty::Const<'tcx>> { + let tcx = selcx.tcx(); + + let ImplSourceUserDefinedData { impl_def_id, substs, nested } = impl_impl_source; + let assoc_item_id = obligation.predicate.item_def_id; + let trait_def_id = tcx.trait_id_of_impl(impl_def_id).unwrap(); + + let param_env = obligation.param_env; + let assoc_ct = match assoc_def(selcx, impl_def_id, assoc_item_id) { + Ok(assoc_ct) => assoc_ct, + Err(ErrorReported) => { + return Progress { term: tcx.const_error(tcx.ty_error()), obligations: nested }; + } + }; + + if !assoc_ct.item.defaultness.has_value() { + return Progress { term: tcx.const_error(tcx.ty_error()), obligations: nested }; + } + let substs = obligation.predicate.substs.rebase_onto(tcx, trait_def_id, substs); + let substs = + translate_substs(selcx.infcx(), param_env, impl_def_id, substs, assoc_ct.defining_node); + let _ty = tcx.type_of(assoc_ct.item.def_id); + // TODO need to figure how to get the const of the assoc_ct.item.def_id + // I'm not sure if there's another tcx query for it. + let _ct = (); + if substs.len() != tcx.generics_of(assoc_ct.item.def_id).count() { + let err = tcx.const_error_with_message( + tcx.ty_error(), + obligation.cause.span, + "impl item and trait item have different parameter counts", + ); + Progress { term: err, obligations: nested } + } else { + // There are no where-clauses on associated consts yet, but if that's + // ever added it would go here. + todo!(); + //Progress { term: ct.subst(tcx, substs), obligations: nested } } } @@ -1905,10 +2164,10 @@ fn assoc_ty_own_obligations<'cx, 'tcx>( /// /// Based on the "projection mode", this lookup may in fact only examine the /// topmost impl. See the comments for `Reveal` for more details. -fn assoc_ty_def( +fn assoc_def( selcx: &SelectionContext<'_, '_>, impl_def_id: DefId, - assoc_ty_def_id: DefId, + assoc_def_id: DefId, ) -> Result { let tcx = selcx.tcx(); let trait_def_id = tcx.impl_trait_ref(impl_def_id).unwrap().def_id; @@ -1920,7 +2179,7 @@ fn assoc_ty_def( // for the associated item at the given impl. // If there is no such item in that impl, this function will fail with a // cycle error if the specialization graph is currently being built. - if let Some(&impl_item_id) = tcx.impl_item_implementor_ids(impl_def_id).get(&assoc_ty_def_id) { + if let Some(&impl_item_id) = tcx.impl_item_implementor_ids(impl_def_id).get(&assoc_def_id) { let item = tcx.associated_item(impl_item_id); let impl_node = specialization_graph::Node::Impl(impl_def_id); return Ok(specialization_graph::LeafDef { @@ -1931,7 +2190,7 @@ fn assoc_ty_def( } let ancestors = trait_def.ancestors(tcx, impl_def_id)?; - if let Some(assoc_item) = ancestors.leaf_def(tcx, assoc_ty_def_id) { + if let Some(assoc_item) = ancestors.leaf_def(tcx, assoc_def_id) { Ok(assoc_item) } else { // This is saying that neither the trait nor @@ -1942,7 +2201,7 @@ fn assoc_ty_def( // should have failed in astconv. bug!( "No associated type `{}` for {}", - tcx.item_name(assoc_ty_def_id), + tcx.item_name(assoc_def_id), tcx.def_path_str(impl_def_id) ) } diff --git a/compiler/rustc_typeck/src/astconv/mod.rs b/compiler/rustc_typeck/src/astconv/mod.rs index 4cf8ddcb8f01c..6124d2906fff0 100644 --- a/compiler/rustc_typeck/src/astconv/mod.rs +++ b/compiler/rustc_typeck/src/astconv/mod.rs @@ -1132,7 +1132,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { // We have already adjusted the item name above, so compare with `ident.normalize_to_macros_2_0()` instead // of calling `filter_by_name_and_kind`. - let assoc_ty = tcx + let assoc_item = tcx .associated_items(candidate.def_id()) .filter_by_name_unhygienic(assoc_ident.name) .find(|i| { @@ -1140,35 +1140,32 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { && i.ident(tcx).normalize_to_macros_2_0() == assoc_ident }) .expect("missing associated type"); - // FIXME(associated_const_equality): need to handle assoc_consts here as well. - if assoc_ty.kind == ty::AssocKind::Const { - tcx.sess - .struct_span_err(path_span, &format!("associated const equality is incomplete")) - .span_label(path_span, "cannot yet relate associated const") - .emit(); - return Err(ErrorReported); - } - if !assoc_ty.vis.is_accessible_from(def_scope, tcx) { + if !assoc_item.vis.is_accessible_from(def_scope, tcx) { + let kind = match assoc_item.kind { + ty::AssocKind::Type => "type", + ty::AssocKind::Const => "const", + _ => unreachable!(), + }; tcx.sess .struct_span_err( binding.span, - &format!("associated type `{}` is private", binding.item_name), + &format!("associated {kind} `{}` is private", binding.item_name), ) - .span_label(binding.span, "private associated type") + .span_label(binding.span, &format!("private associated {kind}")) .emit(); } - tcx.check_stability(assoc_ty.def_id, Some(hir_ref_id), binding.span, None); + tcx.check_stability(assoc_item.def_id, Some(hir_ref_id), binding.span, None); if !speculative { dup_bindings - .entry(assoc_ty.def_id) + .entry(assoc_item.def_id) .and_modify(|prev_span| { self.tcx().sess.emit_err(ValueOfAssociatedStructAlreadySpecified { span: binding.span, prev_span: *prev_span, item_name: binding.item_name, - def_path: tcx.def_path_str(assoc_ty.container.id()), + def_path: tcx.def_path_str(assoc_item.container.id()), }); }) .or_insert(binding.span); @@ -1176,7 +1173,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { // Include substitutions for generic parameters of associated types let projection_ty = candidate.map_bound(|trait_ref| { - let ident = Ident::new(assoc_ty.name, binding.item_name.span); + let ident = Ident::new(assoc_item.name, binding.item_name.span); let item_segment = hir::PathSegment { ident, hir_id: Some(binding.hir_id), @@ -1188,7 +1185,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { let substs_trait_ref_and_assoc_item = self.create_substs_for_associated_item( tcx, path_span, - assoc_ty.def_id, + assoc_item.def_id, &item_segment, trait_ref.substs, ); @@ -1199,14 +1196,14 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { ); ty::ProjectionTy { - item_def_id: assoc_ty.def_id, + item_def_id: assoc_item.def_id, substs: substs_trait_ref_and_assoc_item, } }); if !speculative { // Find any late-bound regions declared in `ty` that are not - // declared in the trait-ref or assoc_ty. These are not well-formed. + // declared in the trait-ref or assoc_item. These are not well-formed. // // Example: // diff --git a/compiler/rustc_typeck/src/collect/type_of.rs b/compiler/rustc_typeck/src/collect/type_of.rs index 63020b7f90f0a..d5430fefc5312 100644 --- a/compiler/rustc_typeck/src/collect/type_of.rs +++ b/compiler/rustc_typeck/src/collect/type_of.rs @@ -1,5 +1,6 @@ use rustc_errors::{Applicability, ErrorReported, StashKey}; use rustc_hir as hir; +use rustc_hir::def::CtorOf; use rustc_hir::def::{DefKind, Res}; use rustc_hir::def_id::{DefId, LocalDefId}; use rustc_hir::intravisit; @@ -170,11 +171,40 @@ pub(super) fn opt_const_param_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> Option< .position(|arg| arg.id() == hir_id) .map(|index| (index, seg)) }); + // FIXME(associated_const_equality): recursively search through the bindings instead + // of just top level. + let (arg_index, segment) = match filtered { None => { - tcx.sess - .delay_span_bug(tcx.def_span(def_id), "no arg matching AnonConst in path"); - return None; + let binding_filtered = path + .segments + .iter() + .filter_map(|seg| seg.args.map(|args| (args.bindings, seg))) + .find_map(|(bindings, seg)| { + bindings + .iter() + .filter_map(|binding| { + if let hir::TypeBindingKind::Equality { term: Term::Const(c) } = + binding.kind + { + Some(c) + } else { + None + } + }) + .position(|ct| ct.hir_id == hir_id) + .map(|idx| (idx, seg)) + }); + match binding_filtered { + Some(inner) => inner, + None => { + tcx.sess.delay_span_bug( + tcx.def_span(def_id), + "no arg matching AnonConst in path", + ); + return None; + } + } } Some(inner) => inner, }; @@ -182,7 +212,6 @@ pub(super) fn opt_const_param_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> Option< // Try to use the segment resolution if it is valid, otherwise we // default to the path resolution. let res = segment.res.filter(|&r| r != Res::Err).unwrap_or(path.res); - use def::CtorOf; let generics = match res { Res::Def(DefKind::Ctor(CtorOf::Variant, _), def_id) => tcx .generics_of(tcx.parent(def_id).and_then(|def_id| tcx.parent(def_id)).unwrap()), @@ -483,15 +512,59 @@ pub(super) fn type_of(tcx: TyCtxt<'_>, def_id: DefId) -> Ty<'_> { .discr_type() .to_ty(tcx), + Node::TraitRef(trait_ref @ &TraitRef { + path, .. + }) if let Some((binding, seg)) = + path + .segments + .iter() + .filter_map(|seg| seg.args.map(|args| (args.bindings, seg))) + .find_map(|(bindings, seg)| { + bindings + .iter() + .filter_map(|binding| { + if let hir::TypeBindingKind::Equality { term: Term::Const(c) } = + binding.kind + { + Some((binding, c)) + } else { + None + } + }) + .find_map(|(binding, ct)| if ct.hir_id == hir_id { + Some((binding, seg)) + } else { + None + }) + }) => + { + // TODO when does this unwrap fail? I have no idea what case it would. + let trait_def_id = trait_ref.trait_def_id().unwrap(); + let assoc_items = tcx.associated_items(trait_def_id); + let assoc_item = assoc_items.find_by_name_and_kind( + tcx, binding.ident, ty::AssocKind::Const, def_id.to_def_id(), + ); + if let Some(assoc_item) = assoc_item { + tcx.type_of(assoc_item.def_id) + } else { + // TODO useful error message here. + tcx.ty_error_with_message( + DUMMY_SP, + &format!("Could not find associated const on trait"), + ) + } + } + Node::GenericParam(&GenericParam { hir_id: param_hir_id, kind: GenericParamKind::Const { default: Some(ct), .. }, .. }) if ct.hir_id == hir_id => tcx.type_of(tcx.hir().local_def_id(param_hir_id)), - x => tcx.ty_error_with_message( + x => + tcx.ty_error_with_message( DUMMY_SP, - &format!("unexpected const parent in type_of(): {:?}", x), + &format!("unexpected const parent in type_of(): {x:?}"), ), } } diff --git a/src/test/ui/associated-consts/assoc-const.rs b/src/test/ui/associated-consts/assoc-const.rs index cd4b42f9f84c8..9c7884c80734c 100644 --- a/src/test/ui/associated-consts/assoc-const.rs +++ b/src/test/ui/associated-consts/assoc-const.rs @@ -1,4 +1,6 @@ +// run-pass #![feature(associated_const_equality)] +#![allow(unused)] pub trait Foo { const N: usize; @@ -13,9 +15,8 @@ impl Foo for Bar { const TEST:usize = 3; -fn foo>() {} -//~^ ERROR associated const equality is incomplete -fn bar>() {} -//~^ ERROR associated const equality is incomplete +fn foo>() {} -fn main() {} +fn main() { + foo::() +} diff --git a/src/test/ui/associated-consts/assoc-const.stderr b/src/test/ui/associated-consts/assoc-const.stderr deleted file mode 100644 index ccaa6fa8ee884..0000000000000 --- a/src/test/ui/associated-consts/assoc-const.stderr +++ /dev/null @@ -1,14 +0,0 @@ -error: associated const equality is incomplete - --> $DIR/assoc-const.rs:16:15 - | -LL | fn foo>() {} - | ^^^ cannot yet relate associated const - -error: associated const equality is incomplete - --> $DIR/assoc-const.rs:18:15 - | -LL | fn bar>() {} - | ^^^^^^^^ cannot yet relate associated const - -error: aborting due to 2 previous errors - From bd03d8167f856044df6430f1dd69142f7511aca8 Mon Sep 17 00:00:00 2001 From: kadmin Date: Wed, 26 Jan 2022 17:02:58 +0000 Subject: [PATCH 2/4] Remove generalization over projection Instead, just use a term everywhere. --- compiler/rustc_infer/src/infer/at.rs | 20 + compiler/rustc_infer/src/traits/project.rs | 8 +- .../src/traits/error_reporting/mod.rs | 30 +- .../src/traits/error_reporting/suggestions.rs | 2 +- .../src/traits/fulfill.rs | 2 +- .../src/traits/project.rs | 385 ++++-------------- .../src/normalize_projection_ty.rs | 5 +- compiler/rustc_typeck/src/collect/type_of.rs | 4 +- .../assoc-const-ty-mismatch.rs | 29 ++ 9 files changed, 160 insertions(+), 325 deletions(-) create mode 100644 src/test/ui/associated-consts/assoc-const-ty-mismatch.rs diff --git a/compiler/rustc_infer/src/infer/at.rs b/compiler/rustc_infer/src/infer/at.rs index cff848eeb6a0f..248e7ef82e481 100644 --- a/compiler/rustc_infer/src/infer/at.rs +++ b/compiler/rustc_infer/src/infer/at.rs @@ -286,6 +286,26 @@ impl<'tcx> ToTrace<'tcx> for &'tcx Const<'tcx> { } } +impl<'tcx> ToTrace<'tcx> for ty::Term<'tcx> { + fn to_trace( + tcx: TyCtxt<'tcx>, + cause: &ObligationCause<'tcx>, + a_is_expected: bool, + a: Self, + b: Self, + ) -> TypeTrace<'tcx> { + match (a, b) { + (ty::Term::Ty(a), ty::Term::Ty(b)) => { + ToTrace::to_trace(tcx, cause, a_is_expected, a, b) + } + (ty::Term::Const(a), ty::Term::Const(b)) => { + ToTrace::to_trace(tcx, cause, a_is_expected, a, b) + } + (_, _) => span_bug!(cause.span, "Unexpected type/const mismatch"), + } + } +} + impl<'tcx> ToTrace<'tcx> for ty::TraitRef<'tcx> { fn to_trace( _: TyCtxt<'tcx>, diff --git a/compiler/rustc_infer/src/traits/project.rs b/compiler/rustc_infer/src/traits/project.rs index 96af16c668781..a1a1168a21d2e 100644 --- a/compiler/rustc_infer/src/traits/project.rs +++ b/compiler/rustc_infer/src/traits/project.rs @@ -93,7 +93,7 @@ pub enum ProjectionCacheEntry<'tcx> { Recur, Error, NormalizedTy { - ty: NormalizedTy<'tcx>, + ty: Normalized<'tcx, ty::Term<'tcx>>, /// If we were able to successfully evaluate the /// corresponding cache entry key during predicate /// evaluation, then this field stores the final @@ -174,7 +174,11 @@ impl<'tcx> ProjectionCache<'_, 'tcx> { } /// Indicates that `key` was normalized to `value`. - pub fn insert_ty(&mut self, key: ProjectionCacheKey<'tcx>, value: NormalizedTy<'tcx>) { + pub fn insert_term( + &mut self, + key: ProjectionCacheKey<'tcx>, + value: Normalized<'tcx, ty::Term<'tcx>>, + ) { debug!( "ProjectionCacheEntry::insert_ty: adding cache entry: key={:?}, value={:?}", key, value 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 37cf41a0ec2e2..d06e8496f59b7 100644 --- a/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs +++ b/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs @@ -1351,19 +1351,31 @@ impl<'a, 'tcx> InferCtxtPrivExt<'a, 'tcx> for InferCtxt<'a, 'tcx> { | ObligationCauseCode::ObjectCastObligation(_) | ObligationCauseCode::OpaqueType ); - // FIXME(associated_const_equality): Handle Consts here - let data_ty = data.term.ty().unwrap(); if let Err(error) = self.at(&obligation.cause, obligation.param_env).eq_exp( is_normalized_ty_expected, normalized_ty, - data_ty, + data.term, ) { - values = Some(infer::ValuePairs::Types(ExpectedFound::new( - is_normalized_ty_expected, - normalized_ty, - data_ty, - ))); - + values = Some(match (normalized_ty, data.term) { + (ty::Term::Ty(normalized_ty), ty::Term::Ty(ty)) => { + infer::ValuePairs::Types(ExpectedFound::new( + is_normalized_ty_expected, + normalized_ty, + ty, + )) + } + (ty::Term::Const(normalized_ct), ty::Term::Const(ct)) => { + infer::ValuePairs::Consts(ExpectedFound::new( + is_normalized_ty_expected, + normalized_ct, + ct, + )) + } + (_, _) => span_bug!( + obligation.cause.span, + "found const or type where other expected" + ), + }); err_buf = error; err = &err_buf; } 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 8c0dbe9b064ea..4bf10edd5cad5 100644 --- a/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs +++ b/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs @@ -2496,7 +2496,7 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> { let try_obligation = self.mk_trait_obligation_with_new_self_ty( obligation.param_env, trait_pred, - normalized_ty, + normalized_ty.ty().unwrap(), ); debug!("suggest_await_before_try: try_trait_obligation {:?}", try_obligation); if self.predicate_may_hold(&try_obligation) diff --git a/compiler/rustc_trait_selection/src/traits/fulfill.rs b/compiler/rustc_trait_selection/src/traits/fulfill.rs index 346590a2de26f..e7897887df706 100644 --- a/compiler/rustc_trait_selection/src/traits/fulfill.rs +++ b/compiler/rustc_trait_selection/src/traits/fulfill.rs @@ -200,7 +200,7 @@ impl<'tcx> TraitEngine<'tcx> for FulfillmentContext<'tcx> { debug!(?normalized_ty); - normalized_ty + normalized_ty.ty().unwrap() } fn register_predicate_obligation( diff --git a/compiler/rustc_trait_selection/src/traits/project.rs b/compiler/rustc_trait_selection/src/traits/project.rs index 8f498f02169f2..ec495bcd65509 100644 --- a/compiler/rustc_trait_selection/src/traits/project.rs +++ b/compiler/rustc_trait_selection/src/traits/project.rs @@ -27,7 +27,7 @@ use rustc_hir::lang_items::LangItem; use rustc_infer::infer::resolve::OpportunisticRegionResolver; use rustc_middle::ty::fold::{TypeFoldable, TypeFolder}; use rustc_middle::ty::subst::Subst; -use rustc_middle::ty::{self, ToPredicate, Ty, TyCtxt}; +use rustc_middle::ty::{self, Term, ToPredicate, Ty, TyCtxt}; use rustc_span::symbol::sym; use std::collections::BTreeMap; @@ -200,7 +200,7 @@ fn project_and_unify_type<'cx, 'tcx>( let infcx = selcx.infcx(); match obligation.predicate.term { ty::Term::Ty(obligation_pred_ty) => { - let normalized_ty = match opt_normalize_projection_type( + let normalized_ty = match opt_normalize_projection_type::( selcx, obligation.param_env, obligation.predicate.projection_ty, @@ -208,14 +208,14 @@ fn project_and_unify_type<'cx, 'tcx>( obligation.recursion_depth, &mut obligations, ) { - Ok(Some(n)) => n, + Ok(Some(n)) => n.ty().unwrap(), Ok(None) => return Ok(Ok(None)), Err(InProgress) => return Ok(Err(InProgress)), }; debug!(?normalized_ty, ?obligations, "project_and_unify_type result"); match infcx .at(&obligation.cause, obligation.param_env) - .eq(normalized_ty, obligation_pred_ty) + .eq(normalized_ty, obligation_pred_ty.into()) { Ok(InferOk { obligations: inferred_obligations, value: () }) => { obligations.extend(inferred_obligations); @@ -227,8 +227,8 @@ fn project_and_unify_type<'cx, 'tcx>( } } } - ty::Term::Const(_obligation_pred_const) => { - let normalized_const = match opt_normalize_projection_const( + ty::Term::Const(obligation_pred_const) => { + let normalized_const = match opt_normalize_projection_type::( selcx, obligation.param_env, obligation.predicate.projection_ty, @@ -236,16 +236,13 @@ fn project_and_unify_type<'cx, 'tcx>( obligation.recursion_depth, &mut obligations, ) { - Ok(Some(n)) => n, + Ok(Some(n)) => n.ct().unwrap(), Ok(None) => return Ok(Ok(None)), Err(InProgress) => return Ok(Err(InProgress)), }; - println!("{:?}", normalized_const); - todo!(); - /* match infcx .at(&obligation.cause, obligation.param_env) - .eq(normalized_ty, obligation_pred_const) + .eq(normalized_const, obligation_pred_const) { Ok(InferOk { obligations: inferred_obligations, value: () }) => { obligations.extend(inferred_obligations); @@ -256,7 +253,6 @@ fn project_and_unify_type<'cx, 'tcx>( Err(MismatchedProjectionTypes { err }) } } - */ } } } @@ -476,7 +472,7 @@ impl<'a, 'b, 'tcx> TypeFolder<'tcx> for AssocTypeNormalizer<'a, 'b, 'tcx> { obligations.len = ?self.obligations.len(), "AssocTypeNormalizer: normalized type" ); - normalized_ty + normalized_ty.ty().unwrap() } ty::Projection(data) => { @@ -496,7 +492,7 @@ impl<'a, 'b, 'tcx> TypeFolder<'tcx> for AssocTypeNormalizer<'a, 'b, 'tcx> { let (data, mapped_regions, mapped_types, mapped_consts) = BoundVarReplacer::replace_bound_vars(infcx, &mut self.universes, data); let data = data.super_fold_with(self); - let normalized_ty = opt_normalize_projection_type( + let normalized_ty = opt_normalize_projection_type::( self.selcx, self.param_env, data, @@ -506,6 +502,7 @@ impl<'a, 'b, 'tcx> TypeFolder<'tcx> for AssocTypeNormalizer<'a, 'b, 'tcx> { ) .ok() .flatten() + .map(|term| term.ty().unwrap()) .map(|normalized_ty| { PlaceholderReplacer::replace_placeholders( infcx, @@ -828,8 +825,8 @@ pub fn normalize_projection_type<'a, 'b, 'tcx>( cause: ObligationCause<'tcx>, depth: usize, obligations: &mut Vec>, -) -> Ty<'tcx> { - opt_normalize_projection_type( +) -> Term<'tcx> { + opt_normalize_projection_type::( selcx, param_env, projection_ty, @@ -844,26 +841,13 @@ pub fn normalize_projection_type<'a, 'b, 'tcx>( // and a deferred predicate to resolve this when more type // information is available. - selcx.infcx().infer_projection(param_env, projection_ty, cause, depth + 1, obligations) + selcx + .infcx() + .infer_projection(param_env, projection_ty, cause, depth + 1, obligations) + .into() }) } -fn opt_normalize_projection_const<'a, 'b, 'tcx>( - selcx: &'a mut SelectionContext<'b, 'tcx>, - param_env: ty::ParamEnv<'tcx>, - projection_const: ty::ProjectionTy<'tcx>, - cause: ObligationCause<'tcx>, - depth: usize, - _obligations: &mut Vec>, -) -> Result>, InProgress> { - let infcx = selcx.infcx(); - let projection_const = infcx.resolve_vars_if_possible(projection_const); - let obligation = Obligation::with_depth(cause.clone(), depth, param_env, projection_const); - // TODO continue working on below - let _projected_const = project_const(selcx, &obligation); - //println!("{:?}", projected_const); - todo!(); -} /// The guts of `normalize`: normalize a specific projection like `::Item`. The result is always a type (and possibly /// additional obligations). Returns `None` in the case of ambiguity, @@ -875,14 +859,14 @@ fn opt_normalize_projection_const<'a, 'b, 'tcx>( /// function takes an obligations vector and appends to it directly, which is /// slightly uglier but avoids the need for an extra short-lived allocation. #[instrument(level = "debug", skip(selcx, param_env, cause, obligations))] -fn opt_normalize_projection_type<'a, 'b, 'tcx>( +fn opt_normalize_projection_type<'a, 'b, 'tcx, const INTO_CONST: bool>( selcx: &'a mut SelectionContext<'b, 'tcx>, param_env: ty::ParamEnv<'tcx>, projection_ty: ty::ProjectionTy<'tcx>, cause: ObligationCause<'tcx>, depth: usize, obligations: &mut Vec>, -) -> Result>, InProgress> { +) -> Result>, InProgress> { let infcx = selcx.infcx(); // Don't use the projection cache in intercrate mode - // the `infcx` may be re-used between intercrate in non-intercrate @@ -949,8 +933,6 @@ fn opt_normalize_projection_type<'a, 'b, 'tcx>( // created (and hence the new ones will quickly be // discarded as duplicated). But when doing trait // evaluation this is not the case, and dropping the trait - // evaluations can causes ICEs (e.g., #43132). - debug!(?ty, "found normalized ty"); obligations.extend(ty.obligations); return Ok(Some(ty.value)); } @@ -958,15 +940,15 @@ fn opt_normalize_projection_type<'a, 'b, 'tcx>( debug!("opt_normalize_projection_type: found error"); let result = normalize_to_error(selcx, param_env, projection_ty, cause, depth); obligations.extend(result.obligations); - return Ok(Some(result.value)); + return Ok(Some(result.value.into())); } } let obligation = Obligation::with_depth(cause.clone(), depth, param_env, projection_ty); - match project_type(selcx, &obligation) { + match project::(selcx, &obligation) { Ok(Projected::Progress(Progress { - term: projected_ty, + term: projected_term, obligations: mut projected_obligations, })) => { // if projection succeeded, then what we get out of this @@ -974,10 +956,9 @@ fn opt_normalize_projection_type<'a, 'b, 'tcx>( // an impl, where-clause etc) and hence we must // re-normalize it - let projected_ty = selcx.infcx().resolve_vars_if_possible(projected_ty); - debug!(?projected_ty, ?depth, ?projected_obligations); + let projected_term = selcx.infcx().resolve_vars_if_possible(projected_term); - let mut result = if projected_ty.has_projections() { + let mut result = if projected_term.has_projections() { let mut normalizer = AssocTypeNormalizer::new( selcx, param_env, @@ -985,13 +966,11 @@ fn opt_normalize_projection_type<'a, 'b, 'tcx>( depth + 1, &mut projected_obligations, ); - let normalized_ty = normalizer.fold(projected_ty); - - debug!(?normalized_ty, ?depth); + let normalized_ty = normalizer.fold(projected_term); Normalized { value: normalized_ty, obligations: projected_obligations } } else { - Normalized { value: projected_ty, obligations: projected_obligations } + Normalized { value: projected_term, obligations: projected_obligations } }; let mut deduped: SsoHashSet<_> = Default::default(); @@ -1003,16 +982,15 @@ fn opt_normalize_projection_type<'a, 'b, 'tcx>( }); if use_cache { - infcx.inner.borrow_mut().projection_cache().insert_ty(cache_key, result.clone()); + infcx.inner.borrow_mut().projection_cache().insert_term(cache_key, result.clone()); } obligations.extend(result.obligations); - Ok(Some(result.value)) + Ok(Some(result.value.into())) } Ok(Projected::NoProgress(projected_ty)) => { - debug!(?projected_ty, "opt_normalize_projection_type: no progress"); let result = Normalized { value: projected_ty, obligations: vec![] }; if use_cache { - infcx.inner.borrow_mut().projection_cache().insert_ty(cache_key, result.clone()); + infcx.inner.borrow_mut().projection_cache().insert_term(cache_key, result.clone()); } // No need to extend `obligations`. Ok(Some(result.value)) @@ -1036,7 +1014,7 @@ fn opt_normalize_projection_type<'a, 'b, 'tcx>( } let result = normalize_to_error(selcx, param_env, projection_ty, cause, depth); obligations.extend(result.obligations); - Ok(Some(result.value)) + Ok(Some(result.value.into())) } } } @@ -1083,22 +1061,19 @@ fn normalize_to_error<'a, 'tcx>( Normalized { value: new_value, obligations: vec![trait_obligation] } } -enum Projected<'tcx, T> { - Progress(Progress<'tcx, T>), - NoProgress(T), +enum Projected<'tcx> { + Progress(Progress<'tcx>), + NoProgress(ty::Term<'tcx>), } -struct Progress<'tcx, T> -where - T: 'tcx, -{ - term: T, +struct Progress<'tcx> { + term: ty::Term<'tcx>, obligations: Vec>, } -impl<'tcx> Progress<'tcx, Ty<'tcx>> { +impl<'tcx> Progress<'tcx> { fn error(tcx: TyCtxt<'tcx>) -> Self { - Progress { term: tcx.ty_error(), obligations: vec![] } + Progress { term: tcx.ty_error().into(), obligations: vec![] } } fn with_addl_obligations(mut self, mut obligations: Vec>) -> Self { @@ -1107,61 +1082,15 @@ impl<'tcx> Progress<'tcx, Ty<'tcx>> { } } -impl<'tcx> Progress<'tcx, &'tcx ty::Const<'tcx>> { - fn error_const(tcx: TyCtxt<'tcx>) -> Self { - Progress { term: tcx.const_error(tcx.ty_error()), obligations: vec![] } - } -} - -fn project_const<'cx, 'tcx>( - selcx: &mut SelectionContext<'cx, 'tcx>, - obligation: &ProjectionTyObligation<'tcx>, -) -> Result>, ProjectionError<'tcx>> { - if !selcx.tcx().recursion_limit().value_within_limit(obligation.recursion_depth) { - return Err(ProjectionError::TraitSelectionError(SelectionError::Overflow)); - } - - if obligation.predicate.references_error() { - return Ok(Projected::Progress(Progress::error_const(selcx.tcx()))); - } - - let mut candidates = ProjectionCandidateSet::None; - - assemble_candidates_from_param_env(selcx, obligation, &mut candidates); - assemble_candidates_from_trait_def(selcx, obligation, &mut candidates); - assemble_candidates_from_object_ty(selcx, obligation, &mut candidates); - if let ProjectionCandidateSet::Single(ProjectionCandidate::Object(_)) = candidates { - } else { - assemble_candidates_from_impls(selcx, obligation, &mut candidates); - }; - match candidates { - ProjectionCandidateSet::Single(candidate) => { - Ok(Projected::Progress(confirm_candidate_const(selcx, obligation, candidate))) - } - ProjectionCandidateSet::None => todo!(), - /* - Ok(Projected::NoProgress( - selcx - .tcx() - .mk_projection(obligation.predicate.item_def_id, obligation.predicate.substs), - )), - */ - // Error occurred while trying to processing impls. - ProjectionCandidateSet::Error(e) => Err(ProjectionError::TraitSelectionError(e)), - // Inherent ambiguity that prevents us from even enumerating the candidates. - ProjectionCandidateSet::Ambiguous => Err(ProjectionError::TooManyCandidates), - } -} - /// Computes the result of a projection type (if we can). /// /// IMPORTANT: /// - `obligation` must be fully normalized #[tracing::instrument(level = "info", skip(selcx))] -fn project_type<'cx, 'tcx>( +fn project<'cx, 'tcx, const INTO_CONST: bool>( selcx: &mut SelectionContext<'cx, 'tcx>, obligation: &ProjectionTyObligation<'tcx>, -) -> Result>, ProjectionError<'tcx>> { +) -> Result, ProjectionError<'tcx>> { if !selcx.tcx().recursion_limit().value_within_limit(obligation.recursion_depth) { // This should really be an immediate error, but some existing code // relies on being able to recover from this. @@ -1194,12 +1123,13 @@ fn project_type<'cx, 'tcx>( match candidates { ProjectionCandidateSet::Single(candidate) => { - Ok(Projected::Progress(confirm_candidate(selcx, obligation, candidate))) + Ok(Projected::Progress(confirm_candidate::(selcx, obligation, candidate))) } ProjectionCandidateSet::None => Ok(Projected::NoProgress( selcx .tcx() - .mk_projection(obligation.predicate.item_def_id, obligation.predicate.substs), + .mk_projection(obligation.predicate.item_def_id, obligation.predicate.substs) + .into(), )), // Error occurred while trying to processing impls. ProjectionCandidateSet::Error(e) => Err(ProjectionError::TraitSelectionError(e)), @@ -1386,10 +1316,7 @@ fn assemble_candidates_from_impls<'cx, 'tcx>( super::ImplSource::Closure(_) | super::ImplSource::Generator(_) | super::ImplSource::FnPointer(_) - | super::ImplSource::TraitAlias(_) => { - debug!(?impl_source); - true - } + | super::ImplSource::TraitAlias(_) => true, super::ImplSource::UserDefined(impl_data) => { // We have to be careful when projecting out of an // impl because of specialization. If we are not in @@ -1598,11 +1525,11 @@ fn assemble_candidates_from_impls<'cx, 'tcx>( }); } -fn confirm_candidate<'cx, 'tcx>( +fn confirm_candidate<'cx, 'tcx, const INTO_CONST: bool>( selcx: &mut SelectionContext<'cx, 'tcx>, obligation: &ProjectionTyObligation<'tcx>, candidate: ProjectionCandidate<'tcx>, -) -> Progress<'tcx, Ty<'tcx>> { +) -> Progress<'tcx> { debug!(?obligation, ?candidate, "confirm_candidate"); let mut progress = match candidate { ProjectionCandidate::ParamEnv(poly_projection) @@ -1615,38 +1542,7 @@ fn confirm_candidate<'cx, 'tcx>( } ProjectionCandidate::Select(impl_source) => { - confirm_select_candidate(selcx, obligation, impl_source) - } - }; - - // When checking for cycle during evaluation, we compare predicates with - // "syntactic" equality. Since normalization generally introduces a type - // with new region variables, we need to resolve them to existing variables - // when possible for this to work. See `auto-trait-projection-recursion.rs` - // for a case where this matters. - if progress.term.has_infer_regions() { - progress.term = OpportunisticRegionResolver::new(selcx.infcx()).fold_ty(progress.term); - } - progress -} - -fn confirm_candidate_const<'cx, 'tcx>( - selcx: &mut SelectionContext<'cx, 'tcx>, - obligation: &ProjectionTyObligation<'tcx>, - candidate: ProjectionCandidate<'tcx>, -) -> Progress<'tcx, &'tcx ty::Const<'tcx>> { - let mut progress = match candidate { - ProjectionCandidate::ParamEnv(poly_projection) - | ProjectionCandidate::Object(poly_projection) => { - confirm_param_env_candidate_const(selcx, obligation, poly_projection, false) - } - - ProjectionCandidate::TraitDef(poly_projection) => { - confirm_param_env_candidate_const(selcx, obligation, poly_projection, true) - } - - ProjectionCandidate::Select(impl_source) => { - confirm_select_candidate_const(selcx, obligation, impl_source) + confirm_select_candidate::(selcx, obligation, impl_source) } }; @@ -1656,18 +1552,21 @@ fn confirm_candidate_const<'cx, 'tcx>( // when possible for this to work. See `auto-trait-projection-recursion.rs` // for a case where this matters. if progress.term.has_infer_regions() { - progress.term = OpportunisticRegionResolver::new(selcx.infcx()).fold_const(progress.term); + progress.term = + progress.term.fold_with(&mut OpportunisticRegionResolver::new(selcx.infcx())); } progress } -fn confirm_select_candidate<'cx, 'tcx>( +fn confirm_select_candidate<'cx, 'tcx, const INTO_CONST: bool>( selcx: &mut SelectionContext<'cx, 'tcx>, obligation: &ProjectionTyObligation<'tcx>, impl_source: Selection<'tcx>, -) -> Progress<'tcx, Ty<'tcx>> { +) -> Progress<'tcx> { match impl_source { - super::ImplSource::UserDefined(data) => confirm_impl_candidate(selcx, obligation, data), + super::ImplSource::UserDefined(data) => { + confirm_impl_candidate::(selcx, obligation, data) + } super::ImplSource::Generator(data) => confirm_generator_candidate(selcx, obligation, data), super::ImplSource::Closure(data) => confirm_closure_candidate(selcx, obligation, data), super::ImplSource::FnPointer(data) => confirm_fn_pointer_candidate(selcx, obligation, data), @@ -1692,42 +1591,11 @@ fn confirm_select_candidate<'cx, 'tcx>( } } -fn confirm_select_candidate_const<'cx, 'tcx>( - selcx: &mut SelectionContext<'cx, 'tcx>, - obligation: &ProjectionTyObligation<'tcx>, - impl_source: Selection<'tcx>, -) -> Progress<'tcx, &'tcx ty::Const<'tcx>> { - match impl_source { - super::ImplSource::UserDefined(data) => { - confirm_impl_candidate_const(selcx, obligation, data) - } - super::ImplSource::Generator(_) - | super::ImplSource::Closure(_) - | super::ImplSource::FnPointer(_) - | super::ImplSource::DiscriminantKind(_) - | super::ImplSource::Pointee(_) => todo!(), - super::ImplSource::Object(_) - | super::ImplSource::AutoImpl(..) - | super::ImplSource::Param(..) - | super::ImplSource::Builtin(..) - | super::ImplSource::TraitUpcasting(_) - | super::ImplSource::TraitAlias(..) - | super::ImplSource::ConstDrop(_) => { - // we don't create Select candidates with this kind of resolution - span_bug!( - obligation.cause.span, - "Cannot project an associated type from `{:?}`", - impl_source - ) - } - } -} - fn confirm_generator_candidate<'cx, 'tcx>( selcx: &mut SelectionContext<'cx, 'tcx>, obligation: &ProjectionTyObligation<'tcx>, impl_source: ImplSourceGeneratorData<'tcx, PredicateObligation<'tcx>>, -) -> Progress<'tcx, Ty<'tcx>> { +) -> Progress<'tcx> { let gen_sig = impl_source.substs.as_generator().poly_sig(); let Normalized { value: gen_sig, obligations } = normalize_with_depth( selcx, @@ -1777,7 +1645,7 @@ fn confirm_discriminant_kind_candidate<'cx, 'tcx>( selcx: &mut SelectionContext<'cx, 'tcx>, obligation: &ProjectionTyObligation<'tcx>, _: ImplSourceDiscriminantKindData, -) -> Progress<'tcx, Ty<'tcx>> { +) -> Progress<'tcx> { let tcx = selcx.tcx(); let self_ty = selcx.infcx().shallow_resolve(obligation.predicate.self_ty()); @@ -1802,7 +1670,7 @@ fn confirm_pointee_candidate<'cx, 'tcx>( selcx: &mut SelectionContext<'cx, 'tcx>, obligation: &ProjectionTyObligation<'tcx>, _: ImplSourcePointeeData, -) -> Progress<'tcx, Ty<'tcx>> { +) -> Progress<'tcx> { let tcx = selcx.tcx(); let self_ty = selcx.infcx().shallow_resolve(obligation.predicate.self_ty()); @@ -1834,7 +1702,7 @@ fn confirm_fn_pointer_candidate<'cx, 'tcx>( selcx: &mut SelectionContext<'cx, 'tcx>, obligation: &ProjectionTyObligation<'tcx>, fn_pointer_impl_source: ImplSourceFnPointerData<'tcx, PredicateObligation<'tcx>>, -) -> Progress<'tcx, Ty<'tcx>> { +) -> Progress<'tcx> { let fn_type = selcx.infcx().shallow_resolve(fn_pointer_impl_source.fn_ty); let sig = fn_type.fn_sig(selcx.tcx()); let Normalized { value: sig, obligations } = normalize_with_depth( @@ -1854,7 +1722,7 @@ fn confirm_closure_candidate<'cx, 'tcx>( selcx: &mut SelectionContext<'cx, 'tcx>, obligation: &ProjectionTyObligation<'tcx>, impl_source: ImplSourceClosureData<'tcx, PredicateObligation<'tcx>>, -) -> Progress<'tcx, Ty<'tcx>> { +) -> Progress<'tcx> { let closure_sig = impl_source.substs.as_closure().sig(); let Normalized { value: closure_sig, obligations } = normalize_with_depth( selcx, @@ -1876,7 +1744,7 @@ fn confirm_callable_candidate<'cx, 'tcx>( obligation: &ProjectionTyObligation<'tcx>, fn_sig: ty::PolyFnSig<'tcx>, flag: util::TupleArgumentsFlag, -) -> Progress<'tcx, Ty<'tcx>> { +) -> Progress<'tcx> { let tcx = selcx.tcx(); debug!(?obligation, ?fn_sig, "confirm_callable_candidate"); @@ -1907,7 +1775,7 @@ fn confirm_param_env_candidate<'cx, 'tcx>( obligation: &ProjectionTyObligation<'tcx>, poly_cache_entry: ty::PolyProjectionPredicate<'tcx>, potentially_unnormalized_candidate: bool, -) -> Progress<'tcx, Ty<'tcx>> { +) -> Progress<'tcx> { let infcx = selcx.infcx(); let cause = &obligation.cause; let param_env = obligation.param_env; @@ -1954,7 +1822,7 @@ fn confirm_param_env_candidate<'cx, 'tcx>( assoc_ty_own_obligations(selcx, obligation, &mut nested_obligations); // FIXME(associated_const_equality): Handle consts here as well? Maybe this progress type should just take // a term instead. - Progress { term: cache_entry.term.ty().unwrap(), obligations: nested_obligations } + Progress { term: cache_entry.term, obligations: nested_obligations } } Err(e) => { let msg = format!( @@ -1963,81 +1831,16 @@ fn confirm_param_env_candidate<'cx, 'tcx>( ); debug!("confirm_param_env_candidate: {}", msg); let err = infcx.tcx.ty_error_with_message(obligation.cause.span, &msg); - Progress { term: err, obligations: vec![] } + Progress { term: err.into(), obligations: vec![] } } } } -fn confirm_param_env_candidate_const<'cx, 'tcx>( - selcx: &mut SelectionContext<'cx, 'tcx>, - obligation: &ProjectionTyObligation<'tcx>, - poly_cache_entry: ty::PolyProjectionPredicate<'tcx>, - potentially_unnormalized_candidate: bool, -) -> Progress<'tcx, &'tcx ty::Const<'tcx>> { - let infcx = selcx.infcx(); - let cause = &obligation.cause; - let param_env = obligation.param_env; - - let (cache_entry, _) = infcx.replace_bound_vars_with_fresh_vars( - cause.span, - LateBoundRegionConversionTime::HigherRankedType, - poly_cache_entry, - ); - - let cache_projection = cache_entry.projection_ty; - let mut nested_obligations = Vec::new(); - let obligation_projection = obligation.predicate; - let obligation_projection = ensure_sufficient_stack(|| { - normalize_with_depth_to( - selcx, - obligation.param_env, - obligation.cause.clone(), - obligation.recursion_depth + 1, - obligation_projection, - &mut nested_obligations, - ) - }); - let cache_projection = if potentially_unnormalized_candidate { - ensure_sufficient_stack(|| { - normalize_with_depth_to( - selcx, - obligation.param_env, - obligation.cause.clone(), - obligation.recursion_depth + 1, - cache_projection, - &mut nested_obligations, - ) - }) - } else { - cache_projection - }; - - match infcx.at(cause, param_env).eq(cache_projection, obligation_projection) { - Ok(InferOk { value: _, obligations }) => { - nested_obligations.extend(obligations); - assoc_ty_own_obligations(selcx, obligation, &mut nested_obligations); - Progress { term: cache_entry.term.ct().unwrap(), obligations: nested_obligations } - } - Err(e) => { - let msg = format!( - "Failed to unify obligation `{:?}` with poly_projection `{:?}`: {:?}", - obligation, poly_cache_entry, e, - ); - let err = infcx.tcx.const_error_with_message( - infcx.tcx.ty_error(), - obligation.cause.span, - &msg, - ); - Progress { term: err, obligations: vec![] } - } - } -} - -fn confirm_impl_candidate<'cx, 'tcx>( +fn confirm_impl_candidate<'cx, 'tcx, const INTO_CONST: bool>( selcx: &mut SelectionContext<'cx, 'tcx>, obligation: &ProjectionTyObligation<'tcx>, impl_impl_source: ImplSourceUserDefinedData<'tcx, PredicateObligation<'tcx>>, -) -> Progress<'tcx, Ty<'tcx>> { +) -> Progress<'tcx> { let tcx = selcx.tcx(); let ImplSourceUserDefinedData { impl_def_id, substs, mut nested } = impl_impl_source; @@ -2047,7 +1850,7 @@ fn confirm_impl_candidate<'cx, 'tcx>( let param_env = obligation.param_env; let assoc_ty = match assoc_def(selcx, impl_def_id, assoc_item_id) { Ok(assoc_ty) => assoc_ty, - Err(ErrorReported) => return Progress { term: tcx.ty_error(), obligations: nested }, + Err(ErrorReported) => return Progress { term: tcx.ty_error().into(), obligations: nested }, }; if !assoc_ty.item.defaultness.has_value() { @@ -2059,7 +1862,7 @@ fn confirm_impl_candidate<'cx, 'tcx>( "confirm_impl_candidate: no associated type {:?} for {:?}", assoc_ty.item.name, obligation.predicate ); - return Progress { term: tcx.ty_error(), obligations: nested }; + return Progress { term: tcx.ty_error().into(), obligations: nested }; } // If we're trying to normalize ` as X>::A` using //`impl X for Vec { type A = Box; }`, then: @@ -2071,59 +1874,23 @@ fn confirm_impl_candidate<'cx, 'tcx>( let substs = translate_substs(selcx.infcx(), param_env, impl_def_id, substs, assoc_ty.defining_node); let ty = tcx.type_of(assoc_ty.item.def_id); + let term: ty::Term<'tcx> = if INTO_CONST { + // FIXME(associated_const_equality): what are the right substs? + let did = ty::WithOptConstParam::unknown(assoc_ty.item.def_id); + let val = ty::ConstKind::Unevaluated(ty::Unevaluated::new(did, substs)); + tcx.mk_const(ty::Const { ty, val }).into() + } else { + ty.into() + }; if substs.len() != tcx.generics_of(assoc_ty.item.def_id).count() { let err = tcx.ty_error_with_message( obligation.cause.span, "impl item and trait item have different parameter counts", ); - Progress { term: err, obligations: nested } + Progress { term: err.into(), obligations: nested } } else { assoc_ty_own_obligations(selcx, obligation, &mut nested); - Progress { term: ty.subst(tcx, substs), obligations: nested } - } -} - -fn confirm_impl_candidate_const<'cx, 'tcx>( - selcx: &mut SelectionContext<'cx, 'tcx>, - obligation: &ProjectionTyObligation<'tcx>, - impl_impl_source: ImplSourceUserDefinedData<'tcx, PredicateObligation<'tcx>>, -) -> Progress<'tcx, &'tcx ty::Const<'tcx>> { - let tcx = selcx.tcx(); - - let ImplSourceUserDefinedData { impl_def_id, substs, nested } = impl_impl_source; - let assoc_item_id = obligation.predicate.item_def_id; - let trait_def_id = tcx.trait_id_of_impl(impl_def_id).unwrap(); - - let param_env = obligation.param_env; - let assoc_ct = match assoc_def(selcx, impl_def_id, assoc_item_id) { - Ok(assoc_ct) => assoc_ct, - Err(ErrorReported) => { - return Progress { term: tcx.const_error(tcx.ty_error()), obligations: nested }; - } - }; - - if !assoc_ct.item.defaultness.has_value() { - return Progress { term: tcx.const_error(tcx.ty_error()), obligations: nested }; - } - let substs = obligation.predicate.substs.rebase_onto(tcx, trait_def_id, substs); - let substs = - translate_substs(selcx.infcx(), param_env, impl_def_id, substs, assoc_ct.defining_node); - let _ty = tcx.type_of(assoc_ct.item.def_id); - // TODO need to figure how to get the const of the assoc_ct.item.def_id - // I'm not sure if there's another tcx query for it. - let _ct = (); - if substs.len() != tcx.generics_of(assoc_ct.item.def_id).count() { - let err = tcx.const_error_with_message( - tcx.ty_error(), - obligation.cause.span, - "impl item and trait item have different parameter counts", - ); - Progress { term: err, obligations: nested } - } else { - // There are no where-clauses on associated consts yet, but if that's - // ever added it would go here. - todo!(); - //Progress { term: ct.subst(tcx, substs), obligations: nested } + Progress { term: term.subst(tcx, substs), obligations: nested } } } diff --git a/compiler/rustc_traits/src/normalize_projection_ty.rs b/compiler/rustc_traits/src/normalize_projection_ty.rs index a8e376838e218..1de50bae31b8c 100644 --- a/compiler/rustc_traits/src/normalize_projection_ty.rs +++ b/compiler/rustc_traits/src/normalize_projection_ty.rs @@ -36,7 +36,10 @@ fn normalize_projection_ty<'tcx>( &mut obligations, ); fulfill_cx.register_predicate_obligations(infcx, obligations); - Ok(NormalizationResult { normalized_ty: answer }) + // FIXME(associated_const_equality): All users of normalize_projection_ty expected + // a type, but there is the possibility it could've been a const now. Maybe change + // it to a Term later? + Ok(NormalizationResult { normalized_ty: answer.ty().unwrap() }) }, ) } diff --git a/compiler/rustc_typeck/src/collect/type_of.rs b/compiler/rustc_typeck/src/collect/type_of.rs index d5430fefc5312..63a8cab3defcc 100644 --- a/compiler/rustc_typeck/src/collect/type_of.rs +++ b/compiler/rustc_typeck/src/collect/type_of.rs @@ -538,7 +538,7 @@ pub(super) fn type_of(tcx: TyCtxt<'_>, def_id: DefId) -> Ty<'_> { }) }) => { - // TODO when does this unwrap fail? I have no idea what case it would. + // FIXME(associated_const_equality) when does this unwrap fail? I have no idea what case it would. let trait_def_id = trait_ref.trait_def_id().unwrap(); let assoc_items = tcx.associated_items(trait_def_id); let assoc_item = assoc_items.find_by_name_and_kind( @@ -547,7 +547,7 @@ pub(super) fn type_of(tcx: TyCtxt<'_>, def_id: DefId) -> Ty<'_> { if let Some(assoc_item) = assoc_item { tcx.type_of(assoc_item.def_id) } else { - // TODO useful error message here. + // FIXME(associated_const_equality): add a useful error message here. tcx.ty_error_with_message( DUMMY_SP, &format!("Could not find associated const on trait"), diff --git a/src/test/ui/associated-consts/assoc-const-ty-mismatch.rs b/src/test/ui/associated-consts/assoc-const-ty-mismatch.rs new file mode 100644 index 0000000000000..53e49e77b3eea --- /dev/null +++ b/src/test/ui/associated-consts/assoc-const-ty-mismatch.rs @@ -0,0 +1,29 @@ +#![feature(associated_const_equality)] +#![allow(unused)] + +pub trait Foo { + const N: usize; +} + +pub trait FooTy { + type T; +} + +pub struct Bar; + +impl Foo for Bar { + const N: usize = 3; +} + +impl FooTy for Bar { + type T = usize; +} + + +fn foo>() {} +fn foo2>() {} + +fn main() { + foo::(); + foo2::(); +} From c654e4d6f4abd794707c9e4e046b2e7f852e642f Mon Sep 17 00:00:00 2001 From: kadmin Date: Fri, 28 Jan 2022 18:14:27 +0000 Subject: [PATCH 3/4] Add ValuePairs::Terms & Fix compile error And use correct substs. --- compiler/rustc_infer/src/infer/at.rs | 12 +-- .../src/infer/error_reporting/mod.rs | 1 + compiler/rustc_infer/src/infer/mod.rs | 1 + .../src/traits/error_reporting/mod.rs | 25 ++---- .../src/traits/project.rs | 39 +++++----- compiler/rustc_typeck/src/astconv/mod.rs | 14 ++++ .../assoc-const-ty-mismatch.rs | 2 + .../assoc-const-ty-mismatch.stderr | 14 ++++ ...nding-to-type-defined-in-supertrait.stderr | 4 +- .../associated-types-eq-3.stderr | 4 +- .../associated-types-eq-hr.stderr | 8 +- .../associated-types-issue-20346.stderr | 4 +- ...ated-types-multiple-types-one-trait.stderr | 8 +- .../hr-associated-type-projection-1.stderr | 4 +- ...mpl-trait-return-missing-constraint.stderr | 7 +- .../ui/associated-types/issue-44153.stderr | 2 +- .../ui/associated-types/issue-72806.stderr | 2 +- .../ui/associated-types/issue-87261.stderr | 77 +++++++------------ ...point-at-type-on-obligation-failure.stderr | 2 +- src/test/ui/error-codes/E0271.stderr | 2 +- .../feature-gate-associated_const_equality.rs | 1 - ...ture-gate-associated_const_equality.stderr | 8 +- .../type-mismatch-signature-deduction.stderr | 2 +- .../issue-68656-unsized-values.stderr | 4 +- .../issue-74684-2.stderr | 2 +- src/test/ui/hrtb/issue-62203-hrtb-ice.stderr | 6 +- .../bound-normalization-fail.stderr | 12 +-- .../ui/impl-trait/issues/issue-70877.stderr | 9 +-- ...ction-mismatch-in-impl-where-clause.stderr | 2 +- src/test/ui/issues/issue-31173.stderr | 4 +- src/test/ui/issues/issue-33941.stderr | 8 +- src/test/ui/issues/issue-39970.stderr | 2 +- .../issue-67039-unsound-pin-partialeq.stderr | 4 +- .../fallback-closure-wrap.fallback.stderr | 4 +- .../check-trait-object-bounds-5.stderr | 2 +- .../check-trait-object-bounds-6.stderr | 2 +- .../type-alias-impl-trait/issue-63355.stderr | 8 +- .../type-alias-impl-trait/issue-89686.stderr | 12 +-- 38 files changed, 143 insertions(+), 181 deletions(-) create mode 100644 src/test/ui/associated-consts/assoc-const-ty-mismatch.stderr diff --git a/compiler/rustc_infer/src/infer/at.rs b/compiler/rustc_infer/src/infer/at.rs index 248e7ef82e481..aa74a92ad1f4f 100644 --- a/compiler/rustc_infer/src/infer/at.rs +++ b/compiler/rustc_infer/src/infer/at.rs @@ -288,21 +288,13 @@ impl<'tcx> ToTrace<'tcx> for &'tcx Const<'tcx> { impl<'tcx> ToTrace<'tcx> for ty::Term<'tcx> { fn to_trace( - tcx: TyCtxt<'tcx>, + _: TyCtxt<'tcx>, cause: &ObligationCause<'tcx>, a_is_expected: bool, a: Self, b: Self, ) -> TypeTrace<'tcx> { - match (a, b) { - (ty::Term::Ty(a), ty::Term::Ty(b)) => { - ToTrace::to_trace(tcx, cause, a_is_expected, a, b) - } - (ty::Term::Const(a), ty::Term::Const(b)) => { - ToTrace::to_trace(tcx, cause, a_is_expected, a, b) - } - (_, _) => span_bug!(cause.span, "Unexpected type/const mismatch"), - } + TypeTrace { cause: cause.clone(), values: Terms(ExpectedFound::new(a_is_expected, a, b)) } } } diff --git a/compiler/rustc_infer/src/infer/error_reporting/mod.rs b/compiler/rustc_infer/src/infer/error_reporting/mod.rs index 1eb8190bd7d2f..24a5f55d53c28 100644 --- a/compiler/rustc_infer/src/infer/error_reporting/mod.rs +++ b/compiler/rustc_infer/src/infer/error_reporting/mod.rs @@ -2127,6 +2127,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { infer::Types(exp_found) => self.expected_found_str_ty(exp_found), infer::Regions(exp_found) => self.expected_found_str(exp_found), infer::Consts(exp_found) => self.expected_found_str(exp_found), + infer::Terms(exp_found) => self.expected_found_str(exp_found), infer::TraitRefs(exp_found) => { let pretty_exp_found = ty::error::ExpectedFound { expected: exp_found.expected.print_only_trait_path(), diff --git a/compiler/rustc_infer/src/infer/mod.rs b/compiler/rustc_infer/src/infer/mod.rs index 266eec08cebf5..330c99f607354 100644 --- a/compiler/rustc_infer/src/infer/mod.rs +++ b/compiler/rustc_infer/src/infer/mod.rs @@ -371,6 +371,7 @@ pub enum ValuePairs<'tcx> { Types(ExpectedFound>), Regions(ExpectedFound>), Consts(ExpectedFound<&'tcx ty::Const<'tcx>>), + Terms(ExpectedFound>), TraitRefs(ExpectedFound>), PolyTraitRefs(ExpectedFound>), } 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 d06e8496f59b7..f16601dd08eb5 100644 --- a/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs +++ b/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs @@ -1356,26 +1356,11 @@ impl<'a, 'tcx> InferCtxtPrivExt<'a, 'tcx> for InferCtxt<'a, 'tcx> { normalized_ty, data.term, ) { - values = Some(match (normalized_ty, data.term) { - (ty::Term::Ty(normalized_ty), ty::Term::Ty(ty)) => { - infer::ValuePairs::Types(ExpectedFound::new( - is_normalized_ty_expected, - normalized_ty, - ty, - )) - } - (ty::Term::Const(normalized_ct), ty::Term::Const(ct)) => { - infer::ValuePairs::Consts(ExpectedFound::new( - is_normalized_ty_expected, - normalized_ct, - ct, - )) - } - (_, _) => span_bug!( - obligation.cause.span, - "found const or type where other expected" - ), - }); + values = Some(infer::ValuePairs::Terms(ExpectedFound::new( + is_normalized_ty_expected, + normalized_ty, + data.term, + ))); err_buf = error; err = &err_buf; } diff --git a/compiler/rustc_trait_selection/src/traits/project.rs b/compiler/rustc_trait_selection/src/traits/project.rs index ec495bcd65509..11cde60f0753a 100644 --- a/compiler/rustc_trait_selection/src/traits/project.rs +++ b/compiler/rustc_trait_selection/src/traits/project.rs @@ -22,6 +22,7 @@ use crate::traits::error_reporting::InferCtxtExt as _; use rustc_data_structures::sso::SsoHashSet; use rustc_data_structures::stack::ensure_sufficient_stack; use rustc_errors::ErrorReported; +use rustc_hir::def::DefKind; use rustc_hir::def_id::DefId; use rustc_hir::lang_items::LangItem; use rustc_infer::infer::resolve::OpportunisticRegionResolver; @@ -200,7 +201,7 @@ fn project_and_unify_type<'cx, 'tcx>( let infcx = selcx.infcx(); match obligation.predicate.term { ty::Term::Ty(obligation_pred_ty) => { - let normalized_ty = match opt_normalize_projection_type::( + let normalized_ty = match opt_normalize_projection_type( selcx, obligation.param_env, obligation.predicate.projection_ty, @@ -215,7 +216,7 @@ fn project_and_unify_type<'cx, 'tcx>( debug!(?normalized_ty, ?obligations, "project_and_unify_type result"); match infcx .at(&obligation.cause, obligation.param_env) - .eq(normalized_ty, obligation_pred_ty.into()) + .eq(normalized_ty, obligation_pred_ty) { Ok(InferOk { obligations: inferred_obligations, value: () }) => { obligations.extend(inferred_obligations); @@ -228,7 +229,7 @@ fn project_and_unify_type<'cx, 'tcx>( } } ty::Term::Const(obligation_pred_const) => { - let normalized_const = match opt_normalize_projection_type::( + let normalized_const = match opt_normalize_projection_type( selcx, obligation.param_env, obligation.predicate.projection_ty, @@ -492,7 +493,7 @@ impl<'a, 'b, 'tcx> TypeFolder<'tcx> for AssocTypeNormalizer<'a, 'b, 'tcx> { let (data, mapped_regions, mapped_types, mapped_consts) = BoundVarReplacer::replace_bound_vars(infcx, &mut self.universes, data); let data = data.super_fold_with(self); - let normalized_ty = opt_normalize_projection_type::( + let normalized_ty = opt_normalize_projection_type( self.selcx, self.param_env, data, @@ -826,7 +827,7 @@ pub fn normalize_projection_type<'a, 'b, 'tcx>( depth: usize, obligations: &mut Vec>, ) -> Term<'tcx> { - opt_normalize_projection_type::( + opt_normalize_projection_type( selcx, param_env, projection_ty, @@ -859,7 +860,7 @@ pub fn normalize_projection_type<'a, 'b, 'tcx>( /// function takes an obligations vector and appends to it directly, which is /// slightly uglier but avoids the need for an extra short-lived allocation. #[instrument(level = "debug", skip(selcx, param_env, cause, obligations))] -fn opt_normalize_projection_type<'a, 'b, 'tcx, const INTO_CONST: bool>( +fn opt_normalize_projection_type<'a, 'b, 'tcx>( selcx: &'a mut SelectionContext<'b, 'tcx>, param_env: ty::ParamEnv<'tcx>, projection_ty: ty::ProjectionTy<'tcx>, @@ -946,7 +947,7 @@ fn opt_normalize_projection_type<'a, 'b, 'tcx, const INTO_CONST: bool>( let obligation = Obligation::with_depth(cause.clone(), depth, param_env, projection_ty); - match project::(selcx, &obligation) { + match project(selcx, &obligation) { Ok(Projected::Progress(Progress { term: projected_term, obligations: mut projected_obligations, @@ -1087,7 +1088,7 @@ impl<'tcx> Progress<'tcx> { /// IMPORTANT: /// - `obligation` must be fully normalized #[tracing::instrument(level = "info", skip(selcx))] -fn project<'cx, 'tcx, const INTO_CONST: bool>( +fn project<'cx, 'tcx>( selcx: &mut SelectionContext<'cx, 'tcx>, obligation: &ProjectionTyObligation<'tcx>, ) -> Result, ProjectionError<'tcx>> { @@ -1123,7 +1124,7 @@ fn project<'cx, 'tcx, const INTO_CONST: bool>( match candidates { ProjectionCandidateSet::Single(candidate) => { - Ok(Projected::Progress(confirm_candidate::(selcx, obligation, candidate))) + Ok(Projected::Progress(confirm_candidate(selcx, obligation, candidate))) } ProjectionCandidateSet::None => Ok(Projected::NoProgress( selcx @@ -1525,7 +1526,7 @@ fn assemble_candidates_from_impls<'cx, 'tcx>( }); } -fn confirm_candidate<'cx, 'tcx, const INTO_CONST: bool>( +fn confirm_candidate<'cx, 'tcx>( selcx: &mut SelectionContext<'cx, 'tcx>, obligation: &ProjectionTyObligation<'tcx>, candidate: ProjectionCandidate<'tcx>, @@ -1542,7 +1543,7 @@ fn confirm_candidate<'cx, 'tcx, const INTO_CONST: bool>( } ProjectionCandidate::Select(impl_source) => { - confirm_select_candidate::(selcx, obligation, impl_source) + confirm_select_candidate(selcx, obligation, impl_source) } }; @@ -1558,15 +1559,13 @@ fn confirm_candidate<'cx, 'tcx, const INTO_CONST: bool>( progress } -fn confirm_select_candidate<'cx, 'tcx, const INTO_CONST: bool>( +fn confirm_select_candidate<'cx, 'tcx>( selcx: &mut SelectionContext<'cx, 'tcx>, obligation: &ProjectionTyObligation<'tcx>, impl_source: Selection<'tcx>, ) -> Progress<'tcx> { match impl_source { - super::ImplSource::UserDefined(data) => { - confirm_impl_candidate::(selcx, obligation, data) - } + super::ImplSource::UserDefined(data) => confirm_impl_candidate(selcx, obligation, data), super::ImplSource::Generator(data) => confirm_generator_candidate(selcx, obligation, data), super::ImplSource::Closure(data) => confirm_closure_candidate(selcx, obligation, data), super::ImplSource::FnPointer(data) => confirm_fn_pointer_candidate(selcx, obligation, data), @@ -1836,7 +1835,7 @@ fn confirm_param_env_candidate<'cx, 'tcx>( } } -fn confirm_impl_candidate<'cx, 'tcx, const INTO_CONST: bool>( +fn confirm_impl_candidate<'cx, 'tcx>( selcx: &mut SelectionContext<'cx, 'tcx>, obligation: &ProjectionTyObligation<'tcx>, impl_impl_source: ImplSourceUserDefinedData<'tcx, PredicateObligation<'tcx>>, @@ -1874,10 +1873,12 @@ fn confirm_impl_candidate<'cx, 'tcx, const INTO_CONST: bool>( let substs = translate_substs(selcx.infcx(), param_env, impl_def_id, substs, assoc_ty.defining_node); let ty = tcx.type_of(assoc_ty.item.def_id); - let term: ty::Term<'tcx> = if INTO_CONST { - // FIXME(associated_const_equality): what are the right substs? + let is_const = matches!(tcx.def_kind(assoc_ty.item.def_id), DefKind::AssocConst); + let term: ty::Term<'tcx> = if is_const { + let identity_substs = + crate::traits::InternalSubsts::identity_for_item(tcx, assoc_ty.item.def_id); let did = ty::WithOptConstParam::unknown(assoc_ty.item.def_id); - let val = ty::ConstKind::Unevaluated(ty::Unevaluated::new(did, substs)); + let val = ty::ConstKind::Unevaluated(ty::Unevaluated::new(did, identity_substs)); tcx.mk_const(ty::Const { ty, val }).into() } else { ty.into() diff --git a/compiler/rustc_typeck/src/astconv/mod.rs b/compiler/rustc_typeck/src/astconv/mod.rs index 6124d2906fff0..06d472214e4d2 100644 --- a/compiler/rustc_typeck/src/astconv/mod.rs +++ b/compiler/rustc_typeck/src/astconv/mod.rs @@ -1244,6 +1244,20 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { // the "projection predicate" for: // // `::Item = u32` + let def_kind = tcx.def_kind(projection_ty.skip_binder().item_def_id); + match (def_kind, term) { + (hir::def::DefKind::AssocTy, ty::Term::Ty(_)) + | (hir::def::DefKind::AssocConst, ty::Term::Const(_)) => (), + (_, _) => { + tcx.sess + .struct_span_err( + binding.span, + "type/const mismatch in equality bind of associated field", + ) + .span_label(binding.span, "type/const Mismatch") + .emit(); + } + } bounds.projection_bounds.push(( projection_ty.map_bound(|projection_ty| ty::ProjectionPredicate { projection_ty, diff --git a/src/test/ui/associated-consts/assoc-const-ty-mismatch.rs b/src/test/ui/associated-consts/assoc-const-ty-mismatch.rs index 53e49e77b3eea..c48f4c63b02c1 100644 --- a/src/test/ui/associated-consts/assoc-const-ty-mismatch.rs +++ b/src/test/ui/associated-consts/assoc-const-ty-mismatch.rs @@ -21,7 +21,9 @@ impl FooTy for Bar { fn foo>() {} +//~^ ERROR type/const mismatch fn foo2>() {} +//~^ ERROR type/const mismatch fn main() { foo::(); diff --git a/src/test/ui/associated-consts/assoc-const-ty-mismatch.stderr b/src/test/ui/associated-consts/assoc-const-ty-mismatch.stderr new file mode 100644 index 0000000000000..71f8375d4e6c5 --- /dev/null +++ b/src/test/ui/associated-consts/assoc-const-ty-mismatch.stderr @@ -0,0 +1,14 @@ +error: type/const mismatch in equality bind of associated field + --> $DIR/assoc-const-ty-mismatch.rs:23:15 + | +LL | fn foo>() {} + | ^^^^^^^ type/const Mismatch + +error: type/const mismatch in equality bind of associated field + --> $DIR/assoc-const-ty-mismatch.rs:25:18 + | +LL | fn foo2>() {} + | ^^^^^^^^ type/const Mismatch + +error: aborting due to 2 previous errors + diff --git a/src/test/ui/associated-types/associated-types-binding-to-type-defined-in-supertrait.stderr b/src/test/ui/associated-types/associated-types-binding-to-type-defined-in-supertrait.stderr index 0cccc6b38a3a9..c14fd7c9ee897 100644 --- a/src/test/ui/associated-types/associated-types-binding-to-type-defined-in-supertrait.stderr +++ b/src/test/ui/associated-types/associated-types-binding-to-type-defined-in-supertrait.stderr @@ -4,7 +4,7 @@ error[E0271]: type mismatch resolving `::Color == Blue` LL | fn b() { blue_car(ModelT); } | ^^^^^^^^ type mismatch resolving `::Color == Blue` | -note: expected this to be `Blue` +note: expected struct `Blue`, found struct `Black` --> $DIR/associated-types-binding-to-type-defined-in-supertrait.rs:16:40 | LL | impl Vehicle for ModelT { type Color = Black; } @@ -21,7 +21,7 @@ error[E0271]: type mismatch resolving `::Color == Black` LL | fn c() { black_car(ModelU); } | ^^^^^^^^^ type mismatch resolving `::Color == Black` | -note: expected this to be `Black` +note: expected struct `Black`, found struct `Blue` --> $DIR/associated-types-binding-to-type-defined-in-supertrait.rs:21:40 | LL | impl Vehicle for ModelU { type Color = Blue; } diff --git a/src/test/ui/associated-types/associated-types-eq-3.stderr b/src/test/ui/associated-types/associated-types-eq-3.stderr index 521907a60445c..64f7a575cd572 100644 --- a/src/test/ui/associated-types/associated-types-eq-3.stderr +++ b/src/test/ui/associated-types/associated-types-eq-3.stderr @@ -19,7 +19,7 @@ error[E0271]: type mismatch resolving `::A == Bar` LL | foo1(a); | ^^^^ type mismatch resolving `::A == Bar` | -note: expected this to be `Bar` +note: expected struct `Bar`, found `usize` --> $DIR/associated-types-eq-3.rs:12:14 | LL | type A = usize; @@ -36,7 +36,7 @@ error[E0271]: type mismatch resolving `::A == Bar` LL | baz(&a); | ^^ type mismatch resolving `::A == Bar` | -note: expected this to be `Bar` +note: expected struct `Bar`, found `usize` --> $DIR/associated-types-eq-3.rs:12:14 | LL | type A = usize; diff --git a/src/test/ui/associated-types/associated-types-eq-hr.stderr b/src/test/ui/associated-types/associated-types-eq-hr.stderr index 1329e1382fd4a..cc69c92b930d1 100644 --- a/src/test/ui/associated-types/associated-types-eq-hr.stderr +++ b/src/test/ui/associated-types/associated-types-eq-hr.stderr @@ -4,13 +4,11 @@ error[E0271]: type mismatch resolving `for<'x> (); | ^^^^^^^^^^^^^^^^^ type mismatch resolving `for<'x> >::A == &'x isize` | -note: expected this to be `&isize` +note: expected `isize`, found `usize` --> $DIR/associated-types-eq-hr.rs:26:14 | LL | type A = &'a usize; | ^^^^^^^^^ - = note: expected reference `&isize` - found reference `&usize` note: required by a bound in `foo` --> $DIR/associated-types-eq-hr.rs:45:36 | @@ -26,13 +24,11 @@ error[E0271]: type mismatch resolving `for<'x> LL | bar::(); | ^^^^^^^^^^^^^^^^ type mismatch resolving `for<'x> >::A == &'x usize` | -note: expected this to be `&usize` +note: expected `usize`, found `isize` --> $DIR/associated-types-eq-hr.rs:14:14 | LL | type A = &'a isize; | ^^^^^^^^^ - = note: expected reference `&usize` - found reference `&isize` note: required by a bound in `bar` --> $DIR/associated-types-eq-hr.rs:52:36 | diff --git a/src/test/ui/associated-types/associated-types-issue-20346.stderr b/src/test/ui/associated-types/associated-types-issue-20346.stderr index 516057e53d25e..4e4b8be462bc6 100644 --- a/src/test/ui/associated-types/associated-types-issue-20346.stderr +++ b/src/test/ui/associated-types/associated-types-issue-20346.stderr @@ -7,12 +7,12 @@ LL | fn test_adapter>>(it: I) { LL | is_iterator_of::, _>(&adapter); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type mismatch resolving ` as Iterator>::Item == Option` | -note: expected this to be `Option` +note: expected enum `Option`, found type parameter `T` --> $DIR/associated-types-issue-20346.rs:23:17 | LL | type Item = T; | ^ - = note: expected enum `Option` + = note: expected type `Option` found type `T` note: required by a bound in `is_iterator_of` --> $DIR/associated-types-issue-20346.rs:15:34 diff --git a/src/test/ui/associated-types/associated-types-multiple-types-one-trait.stderr b/src/test/ui/associated-types/associated-types-multiple-types-one-trait.stderr index 922cf88a04999..eba9483ff222a 100644 --- a/src/test/ui/associated-types/associated-types-multiple-types-one-trait.stderr +++ b/src/test/ui/associated-types/associated-types-multiple-types-one-trait.stderr @@ -4,8 +4,8 @@ error[E0271]: type mismatch resolving `::Y == i32` LL | want_y(t); | ^^^^^^ expected `i32`, found associated type | - = note: expected type `i32` - found associated type `::Y` + = note: expected type `i32` + found type `::Y` note: required by a bound in `want_y` --> $DIR/associated-types-multiple-types-one-trait.rs:44:17 | @@ -22,8 +22,8 @@ error[E0271]: type mismatch resolving `::X == u32` LL | want_x(t); | ^^^^^^ expected `u32`, found associated type | - = note: expected type `u32` - found associated type `::X` + = note: expected type `u32` + found type `::X` note: required by a bound in `want_x` --> $DIR/associated-types-multiple-types-one-trait.rs:42:17 | diff --git a/src/test/ui/associated-types/hr-associated-type-projection-1.stderr b/src/test/ui/associated-types/hr-associated-type-projection-1.stderr index 9c29e969de8da..6c1881fcd29de 100644 --- a/src/test/ui/associated-types/hr-associated-type-projection-1.stderr +++ b/src/test/ui/associated-types/hr-associated-type-projection-1.stderr @@ -4,8 +4,8 @@ error[E0271]: type mismatch resolving `::Target == T` LL | impl UnsafeCopy<'_, T> for T { | - this type parameter ^^^^^^^^^^^^^^^^^ expected associated type, found type parameter `T` | - = note: expected associated type `::Target` - found type parameter `T` + = note: expected type `::Target` + found type `T` help: consider further restricting this bound | LL | impl> UnsafeCopy<'_, T> for T { diff --git a/src/test/ui/associated-types/impl-trait-return-missing-constraint.stderr b/src/test/ui/associated-types/impl-trait-return-missing-constraint.stderr index 283ecea735d41..28ef77ae13762 100644 --- a/src/test/ui/associated-types/impl-trait-return-missing-constraint.stderr +++ b/src/test/ui/associated-types/impl-trait-return-missing-constraint.stderr @@ -1,14 +1,11 @@ error[E0271]: type mismatch resolving `::Item == i32` --> $DIR/impl-trait-return-missing-constraint.rs:25:13 | -LL | fn bar() -> impl Bar { - | -------- the found opaque type -... LL | fn baz() -> impl Bar { | ^^^^^^^^^^^^^^^^^^^^ expected `i32`, found associated type | - = note: expected type `i32` - found associated type `::Item` + = note: expected type `i32` + found type `::Item` help: consider constraining the associated type `::Item` to `i32` | LL | fn bar() -> impl Bar { diff --git a/src/test/ui/associated-types/issue-44153.stderr b/src/test/ui/associated-types/issue-44153.stderr index 200efbe02e661..9244b4821f3e7 100644 --- a/src/test/ui/associated-types/issue-44153.stderr +++ b/src/test/ui/associated-types/issue-44153.stderr @@ -4,7 +4,7 @@ error[E0271]: type mismatch resolving `<() as Array>::Element == &()` LL | <() as Visit>::visit(); | ^^^^^^^^^^^^^^^^^^^^ type mismatch resolving `<() as Array>::Element == &()` | -note: expected this to be `&()` +note: expected `&()`, found `()` --> $DIR/issue-44153.rs:10:20 | LL | type Element = (); diff --git a/src/test/ui/associated-types/issue-72806.stderr b/src/test/ui/associated-types/issue-72806.stderr index e95943f34d549..67b1295d0fe37 100644 --- a/src/test/ui/associated-types/issue-72806.stderr +++ b/src/test/ui/associated-types/issue-72806.stderr @@ -4,7 +4,7 @@ error[E0271]: type mismatch resolving `::Ok == char` LL | type Sibling = Foo2; | ^^^^ type mismatch resolving `::Ok == char` | -note: expected this to be `char` +note: expected `char`, found `u32` --> $DIR/issue-72806.rs:18:15 | LL | type Ok = u32; diff --git a/src/test/ui/associated-types/issue-87261.stderr b/src/test/ui/associated-types/issue-87261.stderr index c00b48abc1c33..e387d34266eb9 100644 --- a/src/test/ui/associated-types/issue-87261.stderr +++ b/src/test/ui/associated-types/issue-87261.stderr @@ -4,8 +4,8 @@ error[E0271]: type mismatch resolving `::Associated == ()` LL | accepts_trait(a); | ^^^^^^^^^^^^^ expected `()`, found associated type | - = note: expected unit type `()` - found associated type `::Associated` + = note: expected type `()` + found type `::Associated` note: required by a bound in `accepts_trait` --> $DIR/issue-87261.rs:43:27 | @@ -22,8 +22,8 @@ error[E0271]: type mismatch resolving `::Associated == ()` LL | accepts_trait(b); | ^^^^^^^^^^^^^ expected `()`, found associated type | - = note: expected unit type `()` - found associated type `::Associated` + = note: expected type `()` + found type `::Associated` = help: consider constraining the associated type `::Associated` to `()` = note: for more information, visit https://doc.rust-lang.org/book/ch19-03-advanced-traits.html note: required by a bound in `accepts_trait` @@ -38,8 +38,8 @@ error[E0271]: type mismatch resolving `::Associated == ()` LL | accepts_trait(c); | ^^^^^^^^^^^^^ expected `()`, found associated type | - = note: expected unit type `()` - found associated type `::Associated` + = note: expected type `()` + found type `::Associated` note: required by a bound in `accepts_trait` --> $DIR/issue-87261.rs:43:27 | @@ -56,8 +56,8 @@ error[E0271]: type mismatch resolving `::Associated == ()` LL | accepts_trait(d); | ^^^^^^^^^^^^^ expected `()`, found associated type | - = note: expected unit type `()` - found associated type `::Associated` + = note: expected type `()` + found type `::Associated` = help: consider constraining the associated type `::Associated` to `()` = note: for more information, visit https://doc.rust-lang.org/book/ch19-03-advanced-traits.html note: required by a bound in `accepts_trait` @@ -72,8 +72,8 @@ error[E0271]: type mismatch resolving `>::Associated == () LL | accepts_generic_trait(e); | ^^^^^^^^^^^^^^^^^^^^^ expected `()`, found associated type | - = note: expected unit type `()` - found associated type `>::Associated` + = note: expected type `()` + found type `>::Associated` note: required by a bound in `accepts_generic_trait` --> $DIR/issue-87261.rs:44:46 | @@ -90,8 +90,8 @@ error[E0271]: type mismatch resolving `>::Associated == () LL | accepts_generic_trait(f); | ^^^^^^^^^^^^^^^^^^^^^ expected `()`, found associated type | - = note: expected unit type `()` - found associated type `>::Associated` + = note: expected type `()` + found type `>::Associated` note: required by a bound in `accepts_generic_trait` --> $DIR/issue-87261.rs:44:46 | @@ -108,8 +108,8 @@ error[E0271]: type mismatch resolving `>::Associated == () LL | accepts_generic_trait(g); | ^^^^^^^^^^^^^^^^^^^^^ expected `()`, found associated type | - = note: expected unit type `()` - found associated type `>::Associated` + = note: expected type `()` + found type `>::Associated` = help: consider constraining the associated type `>::Associated` to `()` = note: for more information, visit https://doc.rust-lang.org/book/ch19-03-advanced-traits.html note: required by a bound in `accepts_generic_trait` @@ -121,14 +121,11 @@ LL | fn accepts_generic_trait>(_: T) {} error[E0271]: type mismatch resolving `::Associated == ()` --> $DIR/issue-87261.rs:79:5 | -LL | fn returns_opaque() -> impl Trait + 'static { - | -------------------- the found opaque type -... LL | accepts_trait(returns_opaque()); | ^^^^^^^^^^^^^ expected `()`, found associated type | - = note: expected unit type `()` - found associated type `::Associated` + = note: expected type `()` + found type `::Associated` note: required by a bound in `accepts_trait` --> $DIR/issue-87261.rs:43:27 | @@ -142,14 +139,11 @@ LL | fn returns_opaque() -> impl Trait + 'static { error[E0271]: type mismatch resolving `::Associated == ()` --> $DIR/issue-87261.rs:82:5 | -LL | fn returns_opaque_derived() -> impl DerivedTrait + 'static { - | --------------------------- the found opaque type -... LL | accepts_trait(returns_opaque_derived()); | ^^^^^^^^^^^^^ expected `()`, found associated type | - = note: expected unit type `()` - found associated type `::Associated` + = note: expected type `()` + found type `::Associated` note: required by a bound in `accepts_trait` --> $DIR/issue-87261.rs:43:27 | @@ -163,14 +157,11 @@ LL | fn returns_opaque_derived() -> impl DerivedTrait + 'static error[E0271]: type mismatch resolving `::Associated == ()` --> $DIR/issue-87261.rs:85:5 | -LL | fn returns_opaque_foo() -> impl Trait + Foo { - | ---------------- the found opaque type -... LL | accepts_trait(returns_opaque_foo()); | ^^^^^^^^^^^^^ expected `()`, found associated type | - = note: expected unit type `()` - found associated type `::Associated` + = note: expected type `()` + found type `::Associated` note: required by a bound in `accepts_trait` --> $DIR/issue-87261.rs:43:27 | @@ -184,14 +175,11 @@ LL | fn returns_opaque_foo() -> impl Trait + Foo { error[E0271]: type mismatch resolving `::Associated == ()` --> $DIR/issue-87261.rs:88:5 | -LL | fn returns_opaque_derived_foo() -> impl DerivedTrait + Foo { - | ----------------------- the found opaque type -... LL | accepts_trait(returns_opaque_derived_foo()); | ^^^^^^^^^^^^^ expected `()`, found associated type | - = note: expected unit type `()` - found associated type `::Associated` + = note: expected type `()` + found type `::Associated` = help: consider constraining the associated type `::Associated` to `()` = note: for more information, visit https://doc.rust-lang.org/book/ch19-03-advanced-traits.html note: required by a bound in `accepts_trait` @@ -203,14 +191,11 @@ LL | fn accepts_trait>(_: T) {} error[E0271]: type mismatch resolving ` as GenericTrait<()>>::Associated == ()` --> $DIR/issue-87261.rs:91:5 | -LL | fn returns_opaque_generic() -> impl GenericTrait<()> + 'static { - | ------------------------------- the found opaque type -... LL | accepts_generic_trait(returns_opaque_generic()); | ^^^^^^^^^^^^^^^^^^^^^ expected `()`, found associated type | - = note: expected unit type `()` - found associated type ` as GenericTrait<()>>::Associated` + = note: expected type `()` + found type ` as GenericTrait<()>>::Associated` note: required by a bound in `accepts_generic_trait` --> $DIR/issue-87261.rs:44:46 | @@ -224,14 +209,11 @@ LL | fn returns_opaque_generic() -> impl GenericTrait<(), Associated = ()> + 'st error[E0271]: type mismatch resolving ` as GenericTrait<()>>::Associated == ()` --> $DIR/issue-87261.rs:94:5 | -LL | fn returns_opaque_generic_foo() -> impl GenericTrait<()> + Foo { - | --------------------------- the found opaque type -... LL | accepts_generic_trait(returns_opaque_generic_foo()); | ^^^^^^^^^^^^^^^^^^^^^ expected `()`, found associated type | - = note: expected unit type `()` - found associated type ` as GenericTrait<()>>::Associated` + = note: expected type `()` + found type ` as GenericTrait<()>>::Associated` note: required by a bound in `accepts_generic_trait` --> $DIR/issue-87261.rs:44:46 | @@ -245,14 +227,11 @@ LL | fn returns_opaque_generic_foo() -> impl GenericTrait<(), Associated = ()> + error[E0271]: type mismatch resolving ` + GenericTrait<()> as GenericTrait<()>>::Associated == ()` --> $DIR/issue-87261.rs:97:5 | -LL | fn returns_opaque_generic_duplicate() -> impl GenericTrait<()> + GenericTrait { - | ---------------------------------------- the found opaque type -... LL | accepts_generic_trait(returns_opaque_generic_duplicate()); | ^^^^^^^^^^^^^^^^^^^^^ expected `()`, found associated type | - = note: expected unit type `()` - found associated type ` + GenericTrait<()> as GenericTrait<()>>::Associated` + = note: expected type `()` + found type ` + GenericTrait<()> as GenericTrait<()>>::Associated` = help: consider constraining the associated type ` + GenericTrait<()> as GenericTrait<()>>::Associated` to `()` = note: for more information, visit https://doc.rust-lang.org/book/ch19-03-advanced-traits.html note: required by a bound in `accepts_generic_trait` diff --git a/src/test/ui/associated-types/point-at-type-on-obligation-failure.stderr b/src/test/ui/associated-types/point-at-type-on-obligation-failure.stderr index 9afbe82c32195..9fd474edff9c5 100644 --- a/src/test/ui/associated-types/point-at-type-on-obligation-failure.stderr +++ b/src/test/ui/associated-types/point-at-type-on-obligation-failure.stderr @@ -4,7 +4,7 @@ error[E0271]: type mismatch resolving `::Ok == ()` LL | type Sibling = Foo2; | ^^^^ type mismatch resolving `::Ok == ()` | -note: expected this to be `()` +note: expected `()`, found `u32` --> $DIR/point-at-type-on-obligation-failure.rs:18:15 | LL | type Ok = u32; diff --git a/src/test/ui/error-codes/E0271.stderr b/src/test/ui/error-codes/E0271.stderr index 9c9c7237d7145..ba5632f47a787 100644 --- a/src/test/ui/error-codes/E0271.stderr +++ b/src/test/ui/error-codes/E0271.stderr @@ -4,7 +4,7 @@ error[E0271]: type mismatch resolving `::AssociatedType == u32` LL | foo(3_i8); | ^^^ type mismatch resolving `::AssociatedType == u32` | -note: expected this to be `u32` +note: expected `u32`, found `&str` --> $DIR/E0271.rs:7:43 | LL | impl Trait for i8 { type AssociatedType = &'static str; } diff --git a/src/test/ui/feature-gates/feature-gate-associated_const_equality.rs b/src/test/ui/feature-gates/feature-gate-associated_const_equality.rs index b51ead2a18866..2534c527be463 100644 --- a/src/test/ui/feature-gates/feature-gate-associated_const_equality.rs +++ b/src/test/ui/feature-gates/feature-gate-associated_const_equality.rs @@ -9,7 +9,6 @@ impl TraitWAssocConst for Demo { fn foo>() {} //~^ ERROR associated const equality -//~| ERROR associated const equality fn main() { foo::(); diff --git a/src/test/ui/feature-gates/feature-gate-associated_const_equality.stderr b/src/test/ui/feature-gates/feature-gate-associated_const_equality.stderr index f4db49c4af884..6563fbcba2e4b 100644 --- a/src/test/ui/feature-gates/feature-gate-associated_const_equality.stderr +++ b/src/test/ui/feature-gates/feature-gate-associated_const_equality.stderr @@ -7,12 +7,6 @@ LL | fn foo>() {} = note: see issue #92827 for more information = help: add `#![feature(associated_const_equality)]` to the crate attributes to enable -error: associated const equality is incomplete - --> $DIR/feature-gate-associated_const_equality.rs:10:28 - | -LL | fn foo>() {} - | ^^^^ cannot yet relate associated const - -error: aborting due to 2 previous errors +error: aborting due to previous error For more information about this error, try `rustc --explain E0658`. diff --git a/src/test/ui/generator/type-mismatch-signature-deduction.stderr b/src/test/ui/generator/type-mismatch-signature-deduction.stderr index 3f1f33a3b123f..3b447a17d523c 100644 --- a/src/test/ui/generator/type-mismatch-signature-deduction.stderr +++ b/src/test/ui/generator/type-mismatch-signature-deduction.stderr @@ -19,7 +19,7 @@ LL | fn foo() -> impl Generator { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `i32`, found enum `Result` | = note: expected type `i32` - found enum `Result<{integer}, _>` + found type `Result<{integer}, _>` error: aborting due to 2 previous errors diff --git a/src/test/ui/generic-associated-types/issue-68656-unsized-values.stderr b/src/test/ui/generic-associated-types/issue-68656-unsized-values.stderr index 8e0f237160196..ee72c8f5d23a9 100644 --- a/src/test/ui/generic-associated-types/issue-68656-unsized-values.stderr +++ b/src/test/ui/generic-associated-types/issue-68656-unsized-values.stderr @@ -6,8 +6,8 @@ LL | impl UnsafeCopy for T { LL | type Item<'a> = T; | ^ expected type parameter `T`, found associated type | - = note: expected type parameter `T` - found associated type `::Target` + = note: expected type `T` + found type `::Target` note: required by a bound in `UnsafeCopy::Item` --> $DIR/issue-68656-unsized-values.rs:6:36 | diff --git a/src/test/ui/generic-associated-types/issue-74684-2.stderr b/src/test/ui/generic-associated-types/issue-74684-2.stderr index f0e03e73f0b3e..7ca5437339216 100644 --- a/src/test/ui/generic-associated-types/issue-74684-2.stderr +++ b/src/test/ui/generic-associated-types/issue-74684-2.stderr @@ -4,7 +4,7 @@ error[E0271]: type mismatch resolving `<{integer} as Fun>::F<'_> == [u8]` LL | bug(Box::new(x)); | ^^^ type mismatch resolving `<{integer} as Fun>::F<'_> == [u8]` | -note: expected this to be `[u8]` +note: expected slice `[u8]`, found `i32` --> $DIR/issue-74684-2.rs:10:18 | LL | type F<'a> = i32; diff --git a/src/test/ui/hrtb/issue-62203-hrtb-ice.stderr b/src/test/ui/hrtb/issue-62203-hrtb-ice.stderr index 0ebba37e4ec70..7a788fbd85653 100644 --- a/src/test/ui/hrtb/issue-62203-hrtb-ice.stderr +++ b/src/test/ui/hrtb/issue-62203-hrtb-ice.stderr @@ -4,13 +4,13 @@ error[E0271]: type mismatch resolving `for<'r> as T0<'r, (&'r u8,)>>::O == <_ as Ty<'r>>::V` | -note: expected this to be `<_ as Ty<'_>>::V` +note: expected associated type, found struct `Unit4` --> $DIR/issue-62203-hrtb-ice.rs:21:14 | LL | type O = T::Output; | ^^^^^^^^^ - = note: expected associated type `<_ as Ty<'_>>::V` - found struct `Unit4` + = note: expected type `<_ as Ty<'_>>::V` + found type `Unit4` = help: consider constraining the associated type `<_ as Ty<'_>>::V` to `Unit4` or calling a method that returns `<_ as Ty<'_>>::V` = note: for more information, visit https://doc.rust-lang.org/book/ch19-03-advanced-traits.html note: required by a bound in `T1::m` diff --git a/src/test/ui/impl-trait/bound-normalization-fail.stderr b/src/test/ui/impl-trait/bound-normalization-fail.stderr index afa21c1a858a2..788c7419559df 100644 --- a/src/test/ui/impl-trait/bound-normalization-fail.stderr +++ b/src/test/ui/impl-trait/bound-normalization-fail.stderr @@ -4,13 +4,13 @@ error[E0271]: type mismatch resolving ` as FooLike>::Output == () -> impl FooLike { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type mismatch resolving ` as FooLike>::Output == ::Assoc` | -note: expected this to be `::Assoc` +note: expected associated type, found `()` --> $DIR/bound-normalization-fail.rs:14:19 | LL | type Output = T; | ^ - = note: expected associated type `::Assoc` - found unit type `()` + = note: expected type `::Assoc` + found type `()` help: consider constraining the associated type `::Assoc` to `()` | LL | fn foo_fail>() -> impl FooLike { @@ -28,13 +28,13 @@ error[E0271]: type mismatch resolving ` as FooLike>::Output == >() -> impl FooLike { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type mismatch resolving ` as FooLike>::Output == >::Assoc` | -note: expected this to be `>::Assoc` +note: expected associated type, found `()` --> $DIR/bound-normalization-fail.rs:14:19 | LL | type Output = T; | ^ - = note: expected associated type `>::Assoc` - found unit type `()` + = note: expected type `>::Assoc` + found type `()` help: consider constraining the associated type `>::Assoc` to `()` | LL | fn foo2_fail<'a, T: Trait<'a, Assoc = ()>>() -> impl FooLike { diff --git a/src/test/ui/impl-trait/issues/issue-70877.stderr b/src/test/ui/impl-trait/issues/issue-70877.stderr index fe48e92da5eac..c187ca6ada860 100644 --- a/src/test/ui/impl-trait/issues/issue-70877.stderr +++ b/src/test/ui/impl-trait/issues/issue-70877.stderr @@ -1,19 +1,16 @@ error[E0271]: type mismatch resolving `::Item == Box<(dyn for<'r> Fn(&'r (dyn ToString + 'r)) -> Option + 'static)>` --> $DIR/issue-70877.rs:7:12 | -LL | type FooRet = impl std::fmt::Debug; - | -------------------- the found opaque type -... LL | type Foo = impl Iterator; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type mismatch resolving `::Item == Box<(dyn for<'r> Fn(&'r (dyn ToString + 'r)) -> Option + 'static)>` | -note: expected this to be `Box<(dyn for<'r> Fn(&'r (dyn ToString + 'r)) -> Option + 'static)>` +note: expected enum `Option`, found opaque type --> $DIR/issue-70877.rs:13:17 | LL | type Item = FooItem; | ^^^^^^^ - = note: expected struct `Box<(dyn for<'r> Fn(&'r (dyn ToString + 'r)) -> Option + 'static)>` - found struct `Box<(dyn for<'r> Fn(&'r (dyn ToString + 'r)) -> impl Debug + 'static)>` + = note: expected type `Box<(dyn for<'r> Fn(&'r (dyn ToString + 'r)) -> Option + 'static)>` + found type `Box<(dyn for<'r> Fn(&'r (dyn ToString + 'r)) -> impl Debug + 'static)>` error: aborting due to previous error diff --git a/src/test/ui/impl-trait/projection-mismatch-in-impl-where-clause.stderr b/src/test/ui/impl-trait/projection-mismatch-in-impl-where-clause.stderr index 65daabe419d3f..bf5a182803ab6 100644 --- a/src/test/ui/impl-trait/projection-mismatch-in-impl-where-clause.stderr +++ b/src/test/ui/impl-trait/projection-mismatch-in-impl-where-clause.stderr @@ -4,7 +4,7 @@ error[E0271]: type mismatch resolving `<() as Super>::Assoc == ()` LL | fn test() -> impl Test { | ^^^^^^^^^ type mismatch resolving `<() as Super>::Assoc == ()` | -note: expected this to be `()` +note: expected `()`, found `u8` --> $DIR/projection-mismatch-in-impl-where-clause.rs:6:18 | LL | type Assoc = u8; diff --git a/src/test/ui/issues/issue-31173.stderr b/src/test/ui/issues/issue-31173.stderr index 982b6118ce659..6d77ab01e83fa 100644 --- a/src/test/ui/issues/issue-31173.stderr +++ b/src/test/ui/issues/issue-31173.stderr @@ -4,8 +4,8 @@ error[E0271]: type mismatch resolving `, [ LL | .cloned() | ^^^^^^ expected reference, found `u8` | - = note: expected reference `&_` - found type `u8` + = note: expected type `&_` + found type `u8` note: required by a bound in `cloned` --> $SRC_DIR/core/src/iter/traits/iterator.rs:LL:COL | diff --git a/src/test/ui/issues/issue-33941.stderr b/src/test/ui/issues/issue-33941.stderr index c6650d60c21e9..5b86981ec78da 100644 --- a/src/test/ui/issues/issue-33941.stderr +++ b/src/test/ui/issues/issue-33941.stderr @@ -4,8 +4,8 @@ error[E0271]: type mismatch resolving ` $SRC_DIR/core/src/iter/traits/iterator.rs:LL:COL | @@ -18,8 +18,8 @@ error[E0271]: type mismatch resolving `>` = note: required because of the requirements on the impl of `IntoIterator` for `Cloned>` diff --git a/src/test/ui/issues/issue-39970.stderr b/src/test/ui/issues/issue-39970.stderr index 1f64a90bc1cf9..73fca41b0c0e7 100644 --- a/src/test/ui/issues/issue-39970.stderr +++ b/src/test/ui/issues/issue-39970.stderr @@ -4,7 +4,7 @@ error[E0271]: type mismatch resolving `for<'a> <() as Array<'a>>::Element == ()` LL | <() as Visit>::visit(); | ^^^^^^^^^^^^^^^^^^^^ type mismatch resolving `for<'a> <() as Array<'a>>::Element == ()` | -note: expected this to be `()` +note: expected `()`, found `&()` --> $DIR/issue-39970.rs:10:20 | LL | type Element = &'a (); diff --git a/src/test/ui/issues/issue-67039-unsound-pin-partialeq.stderr b/src/test/ui/issues/issue-67039-unsound-pin-partialeq.stderr index 733456a1a8bd1..1c7c311b5d2e2 100644 --- a/src/test/ui/issues/issue-67039-unsound-pin-partialeq.stderr +++ b/src/test/ui/issues/issue-67039-unsound-pin-partialeq.stderr @@ -4,8 +4,8 @@ error[E0271]: type mismatch resolving ` as Deref>::Target == Rc LL | let _ = Pin::new(Apple) == Rc::pin(Apple); | ^^ expected struct `Apple`, found struct `Rc` | - = note: expected struct `Apple` - found struct `Rc` + = note: expected type `Apple` + found type `Rc` = note: required because of the requirements on the impl of `PartialEq>>` for `Pin` error: aborting due to previous error diff --git a/src/test/ui/never_type/fallback-closure-wrap.fallback.stderr b/src/test/ui/never_type/fallback-closure-wrap.fallback.stderr index 78d1a3caf4a30..24d45a3062310 100644 --- a/src/test/ui/never_type/fallback-closure-wrap.fallback.stderr +++ b/src/test/ui/never_type/fallback-closure-wrap.fallback.stderr @@ -8,8 +8,8 @@ LL | | panic!("Can't connect to server."); LL | | }) as Box); | |______^ expected `()`, found `!` | - = note: expected unit type `()` - found type `!` + = note: expected type `()` + found type `!` = note: required for the cast to the object type `dyn FnMut()` error: aborting due to previous error diff --git a/src/test/ui/traits/associated_type_bound/check-trait-object-bounds-5.stderr b/src/test/ui/traits/associated_type_bound/check-trait-object-bounds-5.stderr index 4251c1a1ed6cd..bf7691e7f1b38 100644 --- a/src/test/ui/traits/associated_type_bound/check-trait-object-bounds-5.stderr +++ b/src/test/ui/traits/associated_type_bound/check-trait-object-bounds-5.stderr @@ -4,7 +4,7 @@ error[E0271]: type mismatch resolving `::T == i64` LL | is_obj(x) | ^^^^^^ type mismatch resolving `::T == i64` | -note: expected this to be `i64` +note: expected `i64`, found `i32` --> $DIR/check-trait-object-bounds-5.rs:9:14 | LL | type T = U; diff --git a/src/test/ui/traits/associated_type_bound/check-trait-object-bounds-6.stderr b/src/test/ui/traits/associated_type_bound/check-trait-object-bounds-6.stderr index 5b23a513eea9b..016de72847df1 100644 --- a/src/test/ui/traits/associated_type_bound/check-trait-object-bounds-6.stderr +++ b/src/test/ui/traits/associated_type_bound/check-trait-object-bounds-6.stderr @@ -4,7 +4,7 @@ error[E0271]: type mismatch resolving `::T == i64` LL | is_obj(x) | ^^^^^^ type mismatch resolving `::T == i64` | -note: expected this to be `i64` +note: expected `i64`, found `i32` --> $DIR/check-trait-object-bounds-6.rs:9:14 | LL | type T = U; diff --git a/src/test/ui/type-alias-impl-trait/issue-63355.stderr b/src/test/ui/type-alias-impl-trait/issue-63355.stderr index 6fc6b4bfe1f00..860a371b08618 100644 --- a/src/test/ui/type-alias-impl-trait/issue-63355.stderr +++ b/src/test/ui/type-alias-impl-trait/issue-63355.stderr @@ -1,18 +1,16 @@ error[E0271]: type mismatch resolving `<() as Bar>::Foo == ()` --> $DIR/issue-63355.rs:34:20 | -LL | pub type FooImpl = impl Foo; - | -------- the found opaque type LL | pub type BarImpl = impl Bar; | ^^^^^^^^^^^^^^^^^^^^^^^ type mismatch resolving `<() as Bar>::Foo == ()` | -note: expected this to be `()` +note: expected `()`, found opaque type --> $DIR/issue-63355.rs:24:16 | LL | type Foo = FooImpl; | ^^^^^^^ - = note: expected unit type `()` - found opaque type `impl Foo` + = note: expected type `()` + found type `impl Foo` error: aborting due to previous error diff --git a/src/test/ui/type-alias-impl-trait/issue-89686.stderr b/src/test/ui/type-alias-impl-trait/issue-89686.stderr index 19ed9a7476c1b..56e6a5420dd30 100644 --- a/src/test/ui/type-alias-impl-trait/issue-89686.stderr +++ b/src/test/ui/type-alias-impl-trait/issue-89686.stderr @@ -3,17 +3,9 @@ error[E0271]: type mismatch resolving ` as | LL | type G<'a, T> = impl Future; | ^^^^^^^^^^^^^^^^^^^^^^^^ expected `()`, found associated type -... -LL | async move { self.f().await } - | ------------------ the found `async` block | - ::: $SRC_DIR/core/src/future/mod.rs:LL:COL - | -LL | pub const fn from_generator(gen: T) -> impl Future - | ------------------------------- the found opaque type - | - = note: expected unit type `()` - found associated type ` as Future>::Output` + = note: expected type `()` + found type ` as Future>::Output` = help: consider constraining the associated type ` as Future>::Output` to `()` = note: for more information, visit https://doc.rust-lang.org/book/ch19-03-advanced-traits.html From 78fb74a6005642bca0a3da7016f9edbbd99f1846 Mon Sep 17 00:00:00 2001 From: kadmin Date: Tue, 1 Feb 2022 15:28:31 +0000 Subject: [PATCH 4/4] Fix w/ comments --- compiler/rustc_hir/src/hir.rs | 6 ++ compiler/rustc_infer/src/infer/at.rs | 12 ++- .../src/infer/error_reporting/mod.rs | 1 - compiler/rustc_infer/src/infer/mod.rs | 1 - .../src/traits/error_reporting/mod.rs | 25 ++++-- .../src/traits/project.rs | 81 +++++++------------ compiler/rustc_typeck/src/astconv/mod.rs | 12 ++- compiler/rustc_typeck/src/collect/type_of.rs | 64 +++++---------- .../assoc-const-eq-missing.rs | 26 ++++++ .../assoc-const-eq-missing.stderr | 21 +++++ .../assoc-const-ty-mismatch.rs | 4 +- .../assoc-const-ty-mismatch.stderr | 20 ++++- ...nding-to-type-defined-in-supertrait.stderr | 4 +- .../associated-types-eq-3.stderr | 4 +- .../associated-types-eq-hr.stderr | 8 +- .../associated-types-issue-20346.stderr | 4 +- ...ated-types-multiple-types-one-trait.stderr | 8 +- .../hr-associated-type-projection-1.stderr | 4 +- ...mpl-trait-return-missing-constraint.stderr | 7 +- .../ui/associated-types/issue-44153.stderr | 2 +- .../ui/associated-types/issue-72806.stderr | 2 +- .../ui/associated-types/issue-87261.stderr | 77 +++++++++++------- ...point-at-type-on-obligation-failure.stderr | 2 +- src/test/ui/error-codes/E0271.stderr | 2 +- .../type-mismatch-signature-deduction.stderr | 2 +- .../issue-68656-unsized-values.stderr | 4 +- .../issue-74684-2.stderr | 2 +- src/test/ui/hrtb/issue-62203-hrtb-ice.stderr | 6 +- .../bound-normalization-fail.stderr | 12 +-- .../ui/impl-trait/issues/issue-70877.stderr | 9 ++- ...ction-mismatch-in-impl-where-clause.stderr | 2 +- src/test/ui/issues/issue-31173.stderr | 4 +- src/test/ui/issues/issue-33941.stderr | 8 +- src/test/ui/issues/issue-39970.stderr | 2 +- .../issue-67039-unsound-pin-partialeq.stderr | 4 +- .../fallback-closure-wrap.fallback.stderr | 4 +- .../check-trait-object-bounds-5.stderr | 2 +- .../check-trait-object-bounds-6.stderr | 2 +- .../type-alias-impl-trait/issue-63355.stderr | 8 +- .../type-alias-impl-trait/issue-89686.stderr | 12 ++- 40 files changed, 281 insertions(+), 199 deletions(-) create mode 100644 src/test/ui/associated-consts/assoc-const-eq-missing.rs create mode 100644 src/test/ui/associated-consts/assoc-const-eq-missing.stderr diff --git a/compiler/rustc_hir/src/hir.rs b/compiler/rustc_hir/src/hir.rs index a0ed72c9e9e50..68fdbaa6aa025 100644 --- a/compiler/rustc_hir/src/hir.rs +++ b/compiler/rustc_hir/src/hir.rs @@ -2165,6 +2165,12 @@ impl TypeBinding<'_> { _ => panic!("expected equality type binding for parenthesized generic args"), } } + pub fn opt_const(&self) -> Option<&'_ AnonConst> { + match self.kind { + TypeBindingKind::Equality { term: Term::Const(ref c) } => Some(c), + _ => None, + } + } } #[derive(Debug)] diff --git a/compiler/rustc_infer/src/infer/at.rs b/compiler/rustc_infer/src/infer/at.rs index aa74a92ad1f4f..147061dafeb1e 100644 --- a/compiler/rustc_infer/src/infer/at.rs +++ b/compiler/rustc_infer/src/infer/at.rs @@ -288,13 +288,21 @@ impl<'tcx> ToTrace<'tcx> for &'tcx Const<'tcx> { impl<'tcx> ToTrace<'tcx> for ty::Term<'tcx> { fn to_trace( - _: TyCtxt<'tcx>, + tcx: TyCtxt<'tcx>, cause: &ObligationCause<'tcx>, a_is_expected: bool, a: Self, b: Self, ) -> TypeTrace<'tcx> { - TypeTrace { cause: cause.clone(), values: Terms(ExpectedFound::new(a_is_expected, a, b)) } + match (a, b) { + (ty::Term::Ty(a), ty::Term::Ty(b)) => { + ToTrace::to_trace(tcx, cause, a_is_expected, a, b) + } + (ty::Term::Const(a), ty::Term::Const(b)) => { + ToTrace::to_trace(tcx, cause, a_is_expected, a, b) + } + (_, _) => todo!(), + } } } diff --git a/compiler/rustc_infer/src/infer/error_reporting/mod.rs b/compiler/rustc_infer/src/infer/error_reporting/mod.rs index 24a5f55d53c28..1eb8190bd7d2f 100644 --- a/compiler/rustc_infer/src/infer/error_reporting/mod.rs +++ b/compiler/rustc_infer/src/infer/error_reporting/mod.rs @@ -2127,7 +2127,6 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { infer::Types(exp_found) => self.expected_found_str_ty(exp_found), infer::Regions(exp_found) => self.expected_found_str(exp_found), infer::Consts(exp_found) => self.expected_found_str(exp_found), - infer::Terms(exp_found) => self.expected_found_str(exp_found), infer::TraitRefs(exp_found) => { let pretty_exp_found = ty::error::ExpectedFound { expected: exp_found.expected.print_only_trait_path(), diff --git a/compiler/rustc_infer/src/infer/mod.rs b/compiler/rustc_infer/src/infer/mod.rs index 330c99f607354..266eec08cebf5 100644 --- a/compiler/rustc_infer/src/infer/mod.rs +++ b/compiler/rustc_infer/src/infer/mod.rs @@ -371,7 +371,6 @@ pub enum ValuePairs<'tcx> { Types(ExpectedFound>), Regions(ExpectedFound>), Consts(ExpectedFound<&'tcx ty::Const<'tcx>>), - Terms(ExpectedFound>), TraitRefs(ExpectedFound>), PolyTraitRefs(ExpectedFound>), } 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 f16601dd08eb5..d06e8496f59b7 100644 --- a/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs +++ b/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs @@ -1356,11 +1356,26 @@ impl<'a, 'tcx> InferCtxtPrivExt<'a, 'tcx> for InferCtxt<'a, 'tcx> { normalized_ty, data.term, ) { - values = Some(infer::ValuePairs::Terms(ExpectedFound::new( - is_normalized_ty_expected, - normalized_ty, - data.term, - ))); + values = Some(match (normalized_ty, data.term) { + (ty::Term::Ty(normalized_ty), ty::Term::Ty(ty)) => { + infer::ValuePairs::Types(ExpectedFound::new( + is_normalized_ty_expected, + normalized_ty, + ty, + )) + } + (ty::Term::Const(normalized_ct), ty::Term::Const(ct)) => { + infer::ValuePairs::Consts(ExpectedFound::new( + is_normalized_ty_expected, + normalized_ct, + ct, + )) + } + (_, _) => span_bug!( + obligation.cause.span, + "found const or type where other expected" + ), + }); err_buf = error; err = &err_buf; } diff --git a/compiler/rustc_trait_selection/src/traits/project.rs b/compiler/rustc_trait_selection/src/traits/project.rs index 11cde60f0753a..bad4ee3042413 100644 --- a/compiler/rustc_trait_selection/src/traits/project.rs +++ b/compiler/rustc_trait_selection/src/traits/project.rs @@ -199,61 +199,30 @@ fn project_and_unify_type<'cx, 'tcx>( let mut obligations = vec![]; let infcx = selcx.infcx(); - match obligation.predicate.term { - ty::Term::Ty(obligation_pred_ty) => { - let normalized_ty = match opt_normalize_projection_type( - selcx, - obligation.param_env, - obligation.predicate.projection_ty, - obligation.cause.clone(), - obligation.recursion_depth, - &mut obligations, - ) { - Ok(Some(n)) => n.ty().unwrap(), - Ok(None) => return Ok(Ok(None)), - Err(InProgress) => return Ok(Err(InProgress)), - }; - debug!(?normalized_ty, ?obligations, "project_and_unify_type result"); - match infcx - .at(&obligation.cause, obligation.param_env) - .eq(normalized_ty, obligation_pred_ty) - { - Ok(InferOk { obligations: inferred_obligations, value: () }) => { - obligations.extend(inferred_obligations); - Ok(Ok(Some(obligations))) - } - Err(err) => { - debug!("project_and_unify_type: equating types encountered error {:?}", err); - Err(MismatchedProjectionTypes { err }) - } - } + let normalized = match opt_normalize_projection_type( + selcx, + obligation.param_env, + obligation.predicate.projection_ty, + obligation.cause.clone(), + obligation.recursion_depth, + &mut obligations, + ) { + Ok(Some(n)) => n, + Ok(None) => return Ok(Ok(None)), + Err(InProgress) => return Ok(Err(InProgress)), + }; + debug!(?normalized, ?obligations, "project_and_unify_type result"); + match infcx + .at(&obligation.cause, obligation.param_env) + .eq(normalized, obligation.predicate.term) + { + Ok(InferOk { obligations: inferred_obligations, value: () }) => { + obligations.extend(inferred_obligations); + Ok(Ok(Some(obligations))) } - ty::Term::Const(obligation_pred_const) => { - let normalized_const = match opt_normalize_projection_type( - selcx, - obligation.param_env, - obligation.predicate.projection_ty, - obligation.cause.clone(), - obligation.recursion_depth, - &mut obligations, - ) { - Ok(Some(n)) => n.ct().unwrap(), - Ok(None) => return Ok(Ok(None)), - Err(InProgress) => return Ok(Err(InProgress)), - }; - match infcx - .at(&obligation.cause, obligation.param_env) - .eq(normalized_const, obligation_pred_const) - { - Ok(InferOk { obligations: inferred_obligations, value: () }) => { - obligations.extend(inferred_obligations); - Ok(Ok(Some(obligations))) - } - Err(err) => { - debug!("project_and_unify_type: equating consts encountered error {:?}", err); - Err(MismatchedProjectionTypes { err }) - } - } + Err(err) => { + debug!("project_and_unify_type: equating types encountered error {:?}", err); + Err(MismatchedProjectionTypes { err }) } } } @@ -934,6 +903,8 @@ fn opt_normalize_projection_type<'a, 'b, 'tcx>( // created (and hence the new ones will quickly be // discarded as duplicated). But when doing trait // evaluation this is not the case, and dropping the trait + // evaluations can causes ICEs (e.g., #43132). + debug!(?ty, "found normalized ty"); obligations.extend(ty.obligations); return Ok(Some(ty.value)); } @@ -1127,6 +1098,8 @@ fn project<'cx, 'tcx>( Ok(Projected::Progress(confirm_candidate(selcx, obligation, candidate))) } ProjectionCandidateSet::None => Ok(Projected::NoProgress( + // FIXME(associated_const_generics): this may need to change in the future? + // need to investigate whether or not this is fine. selcx .tcx() .mk_projection(obligation.predicate.item_def_id, obligation.predicate.substs) diff --git a/compiler/rustc_typeck/src/astconv/mod.rs b/compiler/rustc_typeck/src/astconv/mod.rs index 06d472214e4d2..5eb9664e1d713 100644 --- a/compiler/rustc_typeck/src/astconv/mod.rs +++ b/compiler/rustc_typeck/src/astconv/mod.rs @@ -1244,17 +1244,23 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { // the "projection predicate" for: // // `::Item = u32` - let def_kind = tcx.def_kind(projection_ty.skip_binder().item_def_id); + let assoc_item_def_id = projection_ty.skip_binder().item_def_id; + let def_kind = tcx.def_kind(assoc_item_def_id); match (def_kind, term) { (hir::def::DefKind::AssocTy, ty::Term::Ty(_)) | (hir::def::DefKind::AssocConst, ty::Term::Const(_)) => (), (_, _) => { + let got = if let ty::Term::Ty(_) = term { "type" } else { "const" }; + let expected = def_kind.descr(assoc_item_def_id); tcx.sess .struct_span_err( binding.span, - "type/const mismatch in equality bind of associated field", + &format!("mismatch in bind of {expected}, got {got}"), + ) + .span_note( + tcx.def_span(assoc_item_def_id), + &format!("{expected} defined here does not match {got}"), ) - .span_label(binding.span, "type/const Mismatch") .emit(); } } diff --git a/compiler/rustc_typeck/src/collect/type_of.rs b/compiler/rustc_typeck/src/collect/type_of.rs index 63a8cab3defcc..7990c14f7737b 100644 --- a/compiler/rustc_typeck/src/collect/type_of.rs +++ b/compiler/rustc_typeck/src/collect/type_of.rs @@ -161,40 +161,26 @@ pub(super) fn opt_const_param_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> Option< // We've encountered an `AnonConst` in some path, so we need to // figure out which generic parameter it corresponds to and return // the relevant type. - let filtered = path - .segments - .iter() - .filter_map(|seg| seg.args.map(|args| (args.args, seg))) - .find_map(|(args, seg)| { - args.iter() - .filter(|arg| arg.is_ty_or_const()) - .position(|arg| arg.id() == hir_id) - .map(|index| (index, seg)) - }); - // FIXME(associated_const_equality): recursively search through the bindings instead - // of just top level. + let filtered = path.segments.iter().find_map(|seg| { + seg.args? + .args + .iter() + .filter(|arg| arg.is_ty_or_const()) + .position(|arg| arg.id() == hir_id) + .map(|index| (index, seg)) + }); + // FIXME(associated_const_generics): can we blend this with iteration above? let (arg_index, segment) = match filtered { None => { - let binding_filtered = path - .segments - .iter() - .filter_map(|seg| seg.args.map(|args| (args.bindings, seg))) - .find_map(|(bindings, seg)| { - bindings - .iter() - .filter_map(|binding| { - if let hir::TypeBindingKind::Equality { term: Term::Const(c) } = - binding.kind - { - Some(c) - } else { - None - } - }) - .position(|ct| ct.hir_id == hir_id) - .map(|idx| (idx, seg)) - }); + let binding_filtered = path.segments.iter().find_map(|seg| { + seg.args? + .bindings + .iter() + .filter_map(TypeBinding::opt_const) + .position(|ct| ct.hir_id == hir_id) + .map(|idx| (idx, seg)) + }); match binding_filtered { Some(inner) => inner, None => { @@ -518,20 +504,10 @@ pub(super) fn type_of(tcx: TyCtxt<'_>, def_id: DefId) -> Ty<'_> { path .segments .iter() - .filter_map(|seg| seg.args.map(|args| (args.bindings, seg))) - .find_map(|(bindings, seg)| { - bindings + .find_map(|seg| { + seg.args?.bindings .iter() - .filter_map(|binding| { - if let hir::TypeBindingKind::Equality { term: Term::Const(c) } = - binding.kind - { - Some((binding, c)) - } else { - None - } - }) - .find_map(|(binding, ct)| if ct.hir_id == hir_id { + .find_map(|binding| if binding.opt_const()?.hir_id == hir_id { Some((binding, seg)) } else { None diff --git a/src/test/ui/associated-consts/assoc-const-eq-missing.rs b/src/test/ui/associated-consts/assoc-const-eq-missing.rs new file mode 100644 index 0000000000000..5e029a12df26f --- /dev/null +++ b/src/test/ui/associated-consts/assoc-const-eq-missing.rs @@ -0,0 +1,26 @@ +#![feature(associated_const_equality)] +#![allow(unused)] + +pub trait Foo { + const N: usize; +} + +pub struct Bar; + +impl Foo for Bar { + const N: usize = 3; +} + + +fn foo1>() {} +//~^ ERROR associated type +fn foo2>() {} +//~^ ERROR associated type +fn foo3>() {} +//~^ ERROR associated type + +fn main() { + foo1::(); + foo2::(); + foo3::(); +} diff --git a/src/test/ui/associated-consts/assoc-const-eq-missing.stderr b/src/test/ui/associated-consts/assoc-const-eq-missing.stderr new file mode 100644 index 0000000000000..b4bd6456c8517 --- /dev/null +++ b/src/test/ui/associated-consts/assoc-const-eq-missing.stderr @@ -0,0 +1,21 @@ +error[E0220]: associated type `Z` not found for `Foo` + --> $DIR/assoc-const-eq-missing.rs:15:16 + | +LL | fn foo1>() {} + | ^ associated type `Z` not found + +error[E0220]: associated type `Z` not found for `Foo` + --> $DIR/assoc-const-eq-missing.rs:17:16 + | +LL | fn foo2>() {} + | ^ associated type `Z` not found + +error[E0220]: associated type `Z` not found for `Foo` + --> $DIR/assoc-const-eq-missing.rs:19:16 + | +LL | fn foo3>() {} + | ^ associated type `Z` not found + +error: aborting due to 3 previous errors + +For more information about this error, try `rustc --explain E0220`. diff --git a/src/test/ui/associated-consts/assoc-const-ty-mismatch.rs b/src/test/ui/associated-consts/assoc-const-ty-mismatch.rs index c48f4c63b02c1..c3293156345a7 100644 --- a/src/test/ui/associated-consts/assoc-const-ty-mismatch.rs +++ b/src/test/ui/associated-consts/assoc-const-ty-mismatch.rs @@ -21,9 +21,9 @@ impl FooTy for Bar { fn foo>() {} -//~^ ERROR type/const mismatch +//~^ ERROR mismatch in fn foo2>() {} -//~^ ERROR type/const mismatch +//~^ ERROR mismatch in fn main() { foo::(); diff --git a/src/test/ui/associated-consts/assoc-const-ty-mismatch.stderr b/src/test/ui/associated-consts/assoc-const-ty-mismatch.stderr index 71f8375d4e6c5..703245145ce4e 100644 --- a/src/test/ui/associated-consts/assoc-const-ty-mismatch.stderr +++ b/src/test/ui/associated-consts/assoc-const-ty-mismatch.stderr @@ -1,14 +1,26 @@ -error: type/const mismatch in equality bind of associated field +error: mismatch in bind of associated constant, got type --> $DIR/assoc-const-ty-mismatch.rs:23:15 | LL | fn foo>() {} - | ^^^^^^^ type/const Mismatch + | ^^^^^^^ + | +note: associated constant defined here does not match type + --> $DIR/assoc-const-ty-mismatch.rs:5:3 + | +LL | const N: usize; + | ^^^^^^^^^^^^^^^ -error: type/const mismatch in equality bind of associated field +error: mismatch in bind of associated type, got const --> $DIR/assoc-const-ty-mismatch.rs:25:18 | LL | fn foo2>() {} - | ^^^^^^^^ type/const Mismatch + | ^^^^^^^^ + | +note: associated type defined here does not match const + --> $DIR/assoc-const-ty-mismatch.rs:9:3 + | +LL | type T; + | ^^^^^^^ error: aborting due to 2 previous errors diff --git a/src/test/ui/associated-types/associated-types-binding-to-type-defined-in-supertrait.stderr b/src/test/ui/associated-types/associated-types-binding-to-type-defined-in-supertrait.stderr index c14fd7c9ee897..0cccc6b38a3a9 100644 --- a/src/test/ui/associated-types/associated-types-binding-to-type-defined-in-supertrait.stderr +++ b/src/test/ui/associated-types/associated-types-binding-to-type-defined-in-supertrait.stderr @@ -4,7 +4,7 @@ error[E0271]: type mismatch resolving `::Color == Blue` LL | fn b() { blue_car(ModelT); } | ^^^^^^^^ type mismatch resolving `::Color == Blue` | -note: expected struct `Blue`, found struct `Black` +note: expected this to be `Blue` --> $DIR/associated-types-binding-to-type-defined-in-supertrait.rs:16:40 | LL | impl Vehicle for ModelT { type Color = Black; } @@ -21,7 +21,7 @@ error[E0271]: type mismatch resolving `::Color == Black` LL | fn c() { black_car(ModelU); } | ^^^^^^^^^ type mismatch resolving `::Color == Black` | -note: expected struct `Black`, found struct `Blue` +note: expected this to be `Black` --> $DIR/associated-types-binding-to-type-defined-in-supertrait.rs:21:40 | LL | impl Vehicle for ModelU { type Color = Blue; } diff --git a/src/test/ui/associated-types/associated-types-eq-3.stderr b/src/test/ui/associated-types/associated-types-eq-3.stderr index 64f7a575cd572..521907a60445c 100644 --- a/src/test/ui/associated-types/associated-types-eq-3.stderr +++ b/src/test/ui/associated-types/associated-types-eq-3.stderr @@ -19,7 +19,7 @@ error[E0271]: type mismatch resolving `::A == Bar` LL | foo1(a); | ^^^^ type mismatch resolving `::A == Bar` | -note: expected struct `Bar`, found `usize` +note: expected this to be `Bar` --> $DIR/associated-types-eq-3.rs:12:14 | LL | type A = usize; @@ -36,7 +36,7 @@ error[E0271]: type mismatch resolving `::A == Bar` LL | baz(&a); | ^^ type mismatch resolving `::A == Bar` | -note: expected struct `Bar`, found `usize` +note: expected this to be `Bar` --> $DIR/associated-types-eq-3.rs:12:14 | LL | type A = usize; diff --git a/src/test/ui/associated-types/associated-types-eq-hr.stderr b/src/test/ui/associated-types/associated-types-eq-hr.stderr index cc69c92b930d1..1329e1382fd4a 100644 --- a/src/test/ui/associated-types/associated-types-eq-hr.stderr +++ b/src/test/ui/associated-types/associated-types-eq-hr.stderr @@ -4,11 +4,13 @@ error[E0271]: type mismatch resolving `for<'x> (); | ^^^^^^^^^^^^^^^^^ type mismatch resolving `for<'x> >::A == &'x isize` | -note: expected `isize`, found `usize` +note: expected this to be `&isize` --> $DIR/associated-types-eq-hr.rs:26:14 | LL | type A = &'a usize; | ^^^^^^^^^ + = note: expected reference `&isize` + found reference `&usize` note: required by a bound in `foo` --> $DIR/associated-types-eq-hr.rs:45:36 | @@ -24,11 +26,13 @@ error[E0271]: type mismatch resolving `for<'x> LL | bar::(); | ^^^^^^^^^^^^^^^^ type mismatch resolving `for<'x> >::A == &'x usize` | -note: expected `usize`, found `isize` +note: expected this to be `&usize` --> $DIR/associated-types-eq-hr.rs:14:14 | LL | type A = &'a isize; | ^^^^^^^^^ + = note: expected reference `&usize` + found reference `&isize` note: required by a bound in `bar` --> $DIR/associated-types-eq-hr.rs:52:36 | diff --git a/src/test/ui/associated-types/associated-types-issue-20346.stderr b/src/test/ui/associated-types/associated-types-issue-20346.stderr index 4e4b8be462bc6..516057e53d25e 100644 --- a/src/test/ui/associated-types/associated-types-issue-20346.stderr +++ b/src/test/ui/associated-types/associated-types-issue-20346.stderr @@ -7,12 +7,12 @@ LL | fn test_adapter>>(it: I) { LL | is_iterator_of::, _>(&adapter); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type mismatch resolving ` as Iterator>::Item == Option` | -note: expected enum `Option`, found type parameter `T` +note: expected this to be `Option` --> $DIR/associated-types-issue-20346.rs:23:17 | LL | type Item = T; | ^ - = note: expected type `Option` + = note: expected enum `Option` found type `T` note: required by a bound in `is_iterator_of` --> $DIR/associated-types-issue-20346.rs:15:34 diff --git a/src/test/ui/associated-types/associated-types-multiple-types-one-trait.stderr b/src/test/ui/associated-types/associated-types-multiple-types-one-trait.stderr index eba9483ff222a..922cf88a04999 100644 --- a/src/test/ui/associated-types/associated-types-multiple-types-one-trait.stderr +++ b/src/test/ui/associated-types/associated-types-multiple-types-one-trait.stderr @@ -4,8 +4,8 @@ error[E0271]: type mismatch resolving `::Y == i32` LL | want_y(t); | ^^^^^^ expected `i32`, found associated type | - = note: expected type `i32` - found type `::Y` + = note: expected type `i32` + found associated type `::Y` note: required by a bound in `want_y` --> $DIR/associated-types-multiple-types-one-trait.rs:44:17 | @@ -22,8 +22,8 @@ error[E0271]: type mismatch resolving `::X == u32` LL | want_x(t); | ^^^^^^ expected `u32`, found associated type | - = note: expected type `u32` - found type `::X` + = note: expected type `u32` + found associated type `::X` note: required by a bound in `want_x` --> $DIR/associated-types-multiple-types-one-trait.rs:42:17 | diff --git a/src/test/ui/associated-types/hr-associated-type-projection-1.stderr b/src/test/ui/associated-types/hr-associated-type-projection-1.stderr index 6c1881fcd29de..9c29e969de8da 100644 --- a/src/test/ui/associated-types/hr-associated-type-projection-1.stderr +++ b/src/test/ui/associated-types/hr-associated-type-projection-1.stderr @@ -4,8 +4,8 @@ error[E0271]: type mismatch resolving `::Target == T` LL | impl UnsafeCopy<'_, T> for T { | - this type parameter ^^^^^^^^^^^^^^^^^ expected associated type, found type parameter `T` | - = note: expected type `::Target` - found type `T` + = note: expected associated type `::Target` + found type parameter `T` help: consider further restricting this bound | LL | impl> UnsafeCopy<'_, T> for T { diff --git a/src/test/ui/associated-types/impl-trait-return-missing-constraint.stderr b/src/test/ui/associated-types/impl-trait-return-missing-constraint.stderr index 28ef77ae13762..283ecea735d41 100644 --- a/src/test/ui/associated-types/impl-trait-return-missing-constraint.stderr +++ b/src/test/ui/associated-types/impl-trait-return-missing-constraint.stderr @@ -1,11 +1,14 @@ error[E0271]: type mismatch resolving `::Item == i32` --> $DIR/impl-trait-return-missing-constraint.rs:25:13 | +LL | fn bar() -> impl Bar { + | -------- the found opaque type +... LL | fn baz() -> impl Bar { | ^^^^^^^^^^^^^^^^^^^^ expected `i32`, found associated type | - = note: expected type `i32` - found type `::Item` + = note: expected type `i32` + found associated type `::Item` help: consider constraining the associated type `::Item` to `i32` | LL | fn bar() -> impl Bar { diff --git a/src/test/ui/associated-types/issue-44153.stderr b/src/test/ui/associated-types/issue-44153.stderr index 9244b4821f3e7..200efbe02e661 100644 --- a/src/test/ui/associated-types/issue-44153.stderr +++ b/src/test/ui/associated-types/issue-44153.stderr @@ -4,7 +4,7 @@ error[E0271]: type mismatch resolving `<() as Array>::Element == &()` LL | <() as Visit>::visit(); | ^^^^^^^^^^^^^^^^^^^^ type mismatch resolving `<() as Array>::Element == &()` | -note: expected `&()`, found `()` +note: expected this to be `&()` --> $DIR/issue-44153.rs:10:20 | LL | type Element = (); diff --git a/src/test/ui/associated-types/issue-72806.stderr b/src/test/ui/associated-types/issue-72806.stderr index 67b1295d0fe37..e95943f34d549 100644 --- a/src/test/ui/associated-types/issue-72806.stderr +++ b/src/test/ui/associated-types/issue-72806.stderr @@ -4,7 +4,7 @@ error[E0271]: type mismatch resolving `::Ok == char` LL | type Sibling = Foo2; | ^^^^ type mismatch resolving `::Ok == char` | -note: expected `char`, found `u32` +note: expected this to be `char` --> $DIR/issue-72806.rs:18:15 | LL | type Ok = u32; diff --git a/src/test/ui/associated-types/issue-87261.stderr b/src/test/ui/associated-types/issue-87261.stderr index e387d34266eb9..c00b48abc1c33 100644 --- a/src/test/ui/associated-types/issue-87261.stderr +++ b/src/test/ui/associated-types/issue-87261.stderr @@ -4,8 +4,8 @@ error[E0271]: type mismatch resolving `::Associated == ()` LL | accepts_trait(a); | ^^^^^^^^^^^^^ expected `()`, found associated type | - = note: expected type `()` - found type `::Associated` + = note: expected unit type `()` + found associated type `::Associated` note: required by a bound in `accepts_trait` --> $DIR/issue-87261.rs:43:27 | @@ -22,8 +22,8 @@ error[E0271]: type mismatch resolving `::Associated == ()` LL | accepts_trait(b); | ^^^^^^^^^^^^^ expected `()`, found associated type | - = note: expected type `()` - found type `::Associated` + = note: expected unit type `()` + found associated type `::Associated` = help: consider constraining the associated type `::Associated` to `()` = note: for more information, visit https://doc.rust-lang.org/book/ch19-03-advanced-traits.html note: required by a bound in `accepts_trait` @@ -38,8 +38,8 @@ error[E0271]: type mismatch resolving `::Associated == ()` LL | accepts_trait(c); | ^^^^^^^^^^^^^ expected `()`, found associated type | - = note: expected type `()` - found type `::Associated` + = note: expected unit type `()` + found associated type `::Associated` note: required by a bound in `accepts_trait` --> $DIR/issue-87261.rs:43:27 | @@ -56,8 +56,8 @@ error[E0271]: type mismatch resolving `::Associated == ()` LL | accepts_trait(d); | ^^^^^^^^^^^^^ expected `()`, found associated type | - = note: expected type `()` - found type `::Associated` + = note: expected unit type `()` + found associated type `::Associated` = help: consider constraining the associated type `::Associated` to `()` = note: for more information, visit https://doc.rust-lang.org/book/ch19-03-advanced-traits.html note: required by a bound in `accepts_trait` @@ -72,8 +72,8 @@ error[E0271]: type mismatch resolving `>::Associated == () LL | accepts_generic_trait(e); | ^^^^^^^^^^^^^^^^^^^^^ expected `()`, found associated type | - = note: expected type `()` - found type `>::Associated` + = note: expected unit type `()` + found associated type `>::Associated` note: required by a bound in `accepts_generic_trait` --> $DIR/issue-87261.rs:44:46 | @@ -90,8 +90,8 @@ error[E0271]: type mismatch resolving `>::Associated == () LL | accepts_generic_trait(f); | ^^^^^^^^^^^^^^^^^^^^^ expected `()`, found associated type | - = note: expected type `()` - found type `>::Associated` + = note: expected unit type `()` + found associated type `>::Associated` note: required by a bound in `accepts_generic_trait` --> $DIR/issue-87261.rs:44:46 | @@ -108,8 +108,8 @@ error[E0271]: type mismatch resolving `>::Associated == () LL | accepts_generic_trait(g); | ^^^^^^^^^^^^^^^^^^^^^ expected `()`, found associated type | - = note: expected type `()` - found type `>::Associated` + = note: expected unit type `()` + found associated type `>::Associated` = help: consider constraining the associated type `>::Associated` to `()` = note: for more information, visit https://doc.rust-lang.org/book/ch19-03-advanced-traits.html note: required by a bound in `accepts_generic_trait` @@ -121,11 +121,14 @@ LL | fn accepts_generic_trait>(_: T) {} error[E0271]: type mismatch resolving `::Associated == ()` --> $DIR/issue-87261.rs:79:5 | +LL | fn returns_opaque() -> impl Trait + 'static { + | -------------------- the found opaque type +... LL | accepts_trait(returns_opaque()); | ^^^^^^^^^^^^^ expected `()`, found associated type | - = note: expected type `()` - found type `::Associated` + = note: expected unit type `()` + found associated type `::Associated` note: required by a bound in `accepts_trait` --> $DIR/issue-87261.rs:43:27 | @@ -139,11 +142,14 @@ LL | fn returns_opaque() -> impl Trait + 'static { error[E0271]: type mismatch resolving `::Associated == ()` --> $DIR/issue-87261.rs:82:5 | +LL | fn returns_opaque_derived() -> impl DerivedTrait + 'static { + | --------------------------- the found opaque type +... LL | accepts_trait(returns_opaque_derived()); | ^^^^^^^^^^^^^ expected `()`, found associated type | - = note: expected type `()` - found type `::Associated` + = note: expected unit type `()` + found associated type `::Associated` note: required by a bound in `accepts_trait` --> $DIR/issue-87261.rs:43:27 | @@ -157,11 +163,14 @@ LL | fn returns_opaque_derived() -> impl DerivedTrait + 'static error[E0271]: type mismatch resolving `::Associated == ()` --> $DIR/issue-87261.rs:85:5 | +LL | fn returns_opaque_foo() -> impl Trait + Foo { + | ---------------- the found opaque type +... LL | accepts_trait(returns_opaque_foo()); | ^^^^^^^^^^^^^ expected `()`, found associated type | - = note: expected type `()` - found type `::Associated` + = note: expected unit type `()` + found associated type `::Associated` note: required by a bound in `accepts_trait` --> $DIR/issue-87261.rs:43:27 | @@ -175,11 +184,14 @@ LL | fn returns_opaque_foo() -> impl Trait + Foo { error[E0271]: type mismatch resolving `::Associated == ()` --> $DIR/issue-87261.rs:88:5 | +LL | fn returns_opaque_derived_foo() -> impl DerivedTrait + Foo { + | ----------------------- the found opaque type +... LL | accepts_trait(returns_opaque_derived_foo()); | ^^^^^^^^^^^^^ expected `()`, found associated type | - = note: expected type `()` - found type `::Associated` + = note: expected unit type `()` + found associated type `::Associated` = help: consider constraining the associated type `::Associated` to `()` = note: for more information, visit https://doc.rust-lang.org/book/ch19-03-advanced-traits.html note: required by a bound in `accepts_trait` @@ -191,11 +203,14 @@ LL | fn accepts_trait>(_: T) {} error[E0271]: type mismatch resolving ` as GenericTrait<()>>::Associated == ()` --> $DIR/issue-87261.rs:91:5 | +LL | fn returns_opaque_generic() -> impl GenericTrait<()> + 'static { + | ------------------------------- the found opaque type +... LL | accepts_generic_trait(returns_opaque_generic()); | ^^^^^^^^^^^^^^^^^^^^^ expected `()`, found associated type | - = note: expected type `()` - found type ` as GenericTrait<()>>::Associated` + = note: expected unit type `()` + found associated type ` as GenericTrait<()>>::Associated` note: required by a bound in `accepts_generic_trait` --> $DIR/issue-87261.rs:44:46 | @@ -209,11 +224,14 @@ LL | fn returns_opaque_generic() -> impl GenericTrait<(), Associated = ()> + 'st error[E0271]: type mismatch resolving ` as GenericTrait<()>>::Associated == ()` --> $DIR/issue-87261.rs:94:5 | +LL | fn returns_opaque_generic_foo() -> impl GenericTrait<()> + Foo { + | --------------------------- the found opaque type +... LL | accepts_generic_trait(returns_opaque_generic_foo()); | ^^^^^^^^^^^^^^^^^^^^^ expected `()`, found associated type | - = note: expected type `()` - found type ` as GenericTrait<()>>::Associated` + = note: expected unit type `()` + found associated type ` as GenericTrait<()>>::Associated` note: required by a bound in `accepts_generic_trait` --> $DIR/issue-87261.rs:44:46 | @@ -227,11 +245,14 @@ LL | fn returns_opaque_generic_foo() -> impl GenericTrait<(), Associated = ()> + error[E0271]: type mismatch resolving ` + GenericTrait<()> as GenericTrait<()>>::Associated == ()` --> $DIR/issue-87261.rs:97:5 | +LL | fn returns_opaque_generic_duplicate() -> impl GenericTrait<()> + GenericTrait { + | ---------------------------------------- the found opaque type +... LL | accepts_generic_trait(returns_opaque_generic_duplicate()); | ^^^^^^^^^^^^^^^^^^^^^ expected `()`, found associated type | - = note: expected type `()` - found type ` + GenericTrait<()> as GenericTrait<()>>::Associated` + = note: expected unit type `()` + found associated type ` + GenericTrait<()> as GenericTrait<()>>::Associated` = help: consider constraining the associated type ` + GenericTrait<()> as GenericTrait<()>>::Associated` to `()` = note: for more information, visit https://doc.rust-lang.org/book/ch19-03-advanced-traits.html note: required by a bound in `accepts_generic_trait` diff --git a/src/test/ui/associated-types/point-at-type-on-obligation-failure.stderr b/src/test/ui/associated-types/point-at-type-on-obligation-failure.stderr index 9fd474edff9c5..9afbe82c32195 100644 --- a/src/test/ui/associated-types/point-at-type-on-obligation-failure.stderr +++ b/src/test/ui/associated-types/point-at-type-on-obligation-failure.stderr @@ -4,7 +4,7 @@ error[E0271]: type mismatch resolving `::Ok == ()` LL | type Sibling = Foo2; | ^^^^ type mismatch resolving `::Ok == ()` | -note: expected `()`, found `u32` +note: expected this to be `()` --> $DIR/point-at-type-on-obligation-failure.rs:18:15 | LL | type Ok = u32; diff --git a/src/test/ui/error-codes/E0271.stderr b/src/test/ui/error-codes/E0271.stderr index ba5632f47a787..9c9c7237d7145 100644 --- a/src/test/ui/error-codes/E0271.stderr +++ b/src/test/ui/error-codes/E0271.stderr @@ -4,7 +4,7 @@ error[E0271]: type mismatch resolving `::AssociatedType == u32` LL | foo(3_i8); | ^^^ type mismatch resolving `::AssociatedType == u32` | -note: expected `u32`, found `&str` +note: expected this to be `u32` --> $DIR/E0271.rs:7:43 | LL | impl Trait for i8 { type AssociatedType = &'static str; } diff --git a/src/test/ui/generator/type-mismatch-signature-deduction.stderr b/src/test/ui/generator/type-mismatch-signature-deduction.stderr index 3b447a17d523c..3f1f33a3b123f 100644 --- a/src/test/ui/generator/type-mismatch-signature-deduction.stderr +++ b/src/test/ui/generator/type-mismatch-signature-deduction.stderr @@ -19,7 +19,7 @@ LL | fn foo() -> impl Generator { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `i32`, found enum `Result` | = note: expected type `i32` - found type `Result<{integer}, _>` + found enum `Result<{integer}, _>` error: aborting due to 2 previous errors diff --git a/src/test/ui/generic-associated-types/issue-68656-unsized-values.stderr b/src/test/ui/generic-associated-types/issue-68656-unsized-values.stderr index ee72c8f5d23a9..8e0f237160196 100644 --- a/src/test/ui/generic-associated-types/issue-68656-unsized-values.stderr +++ b/src/test/ui/generic-associated-types/issue-68656-unsized-values.stderr @@ -6,8 +6,8 @@ LL | impl UnsafeCopy for T { LL | type Item<'a> = T; | ^ expected type parameter `T`, found associated type | - = note: expected type `T` - found type `::Target` + = note: expected type parameter `T` + found associated type `::Target` note: required by a bound in `UnsafeCopy::Item` --> $DIR/issue-68656-unsized-values.rs:6:36 | diff --git a/src/test/ui/generic-associated-types/issue-74684-2.stderr b/src/test/ui/generic-associated-types/issue-74684-2.stderr index 7ca5437339216..f0e03e73f0b3e 100644 --- a/src/test/ui/generic-associated-types/issue-74684-2.stderr +++ b/src/test/ui/generic-associated-types/issue-74684-2.stderr @@ -4,7 +4,7 @@ error[E0271]: type mismatch resolving `<{integer} as Fun>::F<'_> == [u8]` LL | bug(Box::new(x)); | ^^^ type mismatch resolving `<{integer} as Fun>::F<'_> == [u8]` | -note: expected slice `[u8]`, found `i32` +note: expected this to be `[u8]` --> $DIR/issue-74684-2.rs:10:18 | LL | type F<'a> = i32; diff --git a/src/test/ui/hrtb/issue-62203-hrtb-ice.stderr b/src/test/ui/hrtb/issue-62203-hrtb-ice.stderr index 7a788fbd85653..0ebba37e4ec70 100644 --- a/src/test/ui/hrtb/issue-62203-hrtb-ice.stderr +++ b/src/test/ui/hrtb/issue-62203-hrtb-ice.stderr @@ -4,13 +4,13 @@ error[E0271]: type mismatch resolving `for<'r> as T0<'r, (&'r u8,)>>::O == <_ as Ty<'r>>::V` | -note: expected associated type, found struct `Unit4` +note: expected this to be `<_ as Ty<'_>>::V` --> $DIR/issue-62203-hrtb-ice.rs:21:14 | LL | type O = T::Output; | ^^^^^^^^^ - = note: expected type `<_ as Ty<'_>>::V` - found type `Unit4` + = note: expected associated type `<_ as Ty<'_>>::V` + found struct `Unit4` = help: consider constraining the associated type `<_ as Ty<'_>>::V` to `Unit4` or calling a method that returns `<_ as Ty<'_>>::V` = note: for more information, visit https://doc.rust-lang.org/book/ch19-03-advanced-traits.html note: required by a bound in `T1::m` diff --git a/src/test/ui/impl-trait/bound-normalization-fail.stderr b/src/test/ui/impl-trait/bound-normalization-fail.stderr index 788c7419559df..afa21c1a858a2 100644 --- a/src/test/ui/impl-trait/bound-normalization-fail.stderr +++ b/src/test/ui/impl-trait/bound-normalization-fail.stderr @@ -4,13 +4,13 @@ error[E0271]: type mismatch resolving ` as FooLike>::Output == () -> impl FooLike { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type mismatch resolving ` as FooLike>::Output == ::Assoc` | -note: expected associated type, found `()` +note: expected this to be `::Assoc` --> $DIR/bound-normalization-fail.rs:14:19 | LL | type Output = T; | ^ - = note: expected type `::Assoc` - found type `()` + = note: expected associated type `::Assoc` + found unit type `()` help: consider constraining the associated type `::Assoc` to `()` | LL | fn foo_fail>() -> impl FooLike { @@ -28,13 +28,13 @@ error[E0271]: type mismatch resolving ` as FooLike>::Output == >() -> impl FooLike { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type mismatch resolving ` as FooLike>::Output == >::Assoc` | -note: expected associated type, found `()` +note: expected this to be `>::Assoc` --> $DIR/bound-normalization-fail.rs:14:19 | LL | type Output = T; | ^ - = note: expected type `>::Assoc` - found type `()` + = note: expected associated type `>::Assoc` + found unit type `()` help: consider constraining the associated type `>::Assoc` to `()` | LL | fn foo2_fail<'a, T: Trait<'a, Assoc = ()>>() -> impl FooLike { diff --git a/src/test/ui/impl-trait/issues/issue-70877.stderr b/src/test/ui/impl-trait/issues/issue-70877.stderr index c187ca6ada860..fe48e92da5eac 100644 --- a/src/test/ui/impl-trait/issues/issue-70877.stderr +++ b/src/test/ui/impl-trait/issues/issue-70877.stderr @@ -1,16 +1,19 @@ error[E0271]: type mismatch resolving `::Item == Box<(dyn for<'r> Fn(&'r (dyn ToString + 'r)) -> Option + 'static)>` --> $DIR/issue-70877.rs:7:12 | +LL | type FooRet = impl std::fmt::Debug; + | -------------------- the found opaque type +... LL | type Foo = impl Iterator; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type mismatch resolving `::Item == Box<(dyn for<'r> Fn(&'r (dyn ToString + 'r)) -> Option + 'static)>` | -note: expected enum `Option`, found opaque type +note: expected this to be `Box<(dyn for<'r> Fn(&'r (dyn ToString + 'r)) -> Option + 'static)>` --> $DIR/issue-70877.rs:13:17 | LL | type Item = FooItem; | ^^^^^^^ - = note: expected type `Box<(dyn for<'r> Fn(&'r (dyn ToString + 'r)) -> Option + 'static)>` - found type `Box<(dyn for<'r> Fn(&'r (dyn ToString + 'r)) -> impl Debug + 'static)>` + = note: expected struct `Box<(dyn for<'r> Fn(&'r (dyn ToString + 'r)) -> Option + 'static)>` + found struct `Box<(dyn for<'r> Fn(&'r (dyn ToString + 'r)) -> impl Debug + 'static)>` error: aborting due to previous error diff --git a/src/test/ui/impl-trait/projection-mismatch-in-impl-where-clause.stderr b/src/test/ui/impl-trait/projection-mismatch-in-impl-where-clause.stderr index bf5a182803ab6..65daabe419d3f 100644 --- a/src/test/ui/impl-trait/projection-mismatch-in-impl-where-clause.stderr +++ b/src/test/ui/impl-trait/projection-mismatch-in-impl-where-clause.stderr @@ -4,7 +4,7 @@ error[E0271]: type mismatch resolving `<() as Super>::Assoc == ()` LL | fn test() -> impl Test { | ^^^^^^^^^ type mismatch resolving `<() as Super>::Assoc == ()` | -note: expected `()`, found `u8` +note: expected this to be `()` --> $DIR/projection-mismatch-in-impl-where-clause.rs:6:18 | LL | type Assoc = u8; diff --git a/src/test/ui/issues/issue-31173.stderr b/src/test/ui/issues/issue-31173.stderr index 6d77ab01e83fa..982b6118ce659 100644 --- a/src/test/ui/issues/issue-31173.stderr +++ b/src/test/ui/issues/issue-31173.stderr @@ -4,8 +4,8 @@ error[E0271]: type mismatch resolving `, [ LL | .cloned() | ^^^^^^ expected reference, found `u8` | - = note: expected type `&_` - found type `u8` + = note: expected reference `&_` + found type `u8` note: required by a bound in `cloned` --> $SRC_DIR/core/src/iter/traits/iterator.rs:LL:COL | diff --git a/src/test/ui/issues/issue-33941.stderr b/src/test/ui/issues/issue-33941.stderr index 5b86981ec78da..c6650d60c21e9 100644 --- a/src/test/ui/issues/issue-33941.stderr +++ b/src/test/ui/issues/issue-33941.stderr @@ -4,8 +4,8 @@ error[E0271]: type mismatch resolving ` $SRC_DIR/core/src/iter/traits/iterator.rs:LL:COL | @@ -18,8 +18,8 @@ error[E0271]: type mismatch resolving `>` = note: required because of the requirements on the impl of `IntoIterator` for `Cloned>` diff --git a/src/test/ui/issues/issue-39970.stderr b/src/test/ui/issues/issue-39970.stderr index 73fca41b0c0e7..1f64a90bc1cf9 100644 --- a/src/test/ui/issues/issue-39970.stderr +++ b/src/test/ui/issues/issue-39970.stderr @@ -4,7 +4,7 @@ error[E0271]: type mismatch resolving `for<'a> <() as Array<'a>>::Element == ()` LL | <() as Visit>::visit(); | ^^^^^^^^^^^^^^^^^^^^ type mismatch resolving `for<'a> <() as Array<'a>>::Element == ()` | -note: expected `()`, found `&()` +note: expected this to be `()` --> $DIR/issue-39970.rs:10:20 | LL | type Element = &'a (); diff --git a/src/test/ui/issues/issue-67039-unsound-pin-partialeq.stderr b/src/test/ui/issues/issue-67039-unsound-pin-partialeq.stderr index 1c7c311b5d2e2..733456a1a8bd1 100644 --- a/src/test/ui/issues/issue-67039-unsound-pin-partialeq.stderr +++ b/src/test/ui/issues/issue-67039-unsound-pin-partialeq.stderr @@ -4,8 +4,8 @@ error[E0271]: type mismatch resolving ` as Deref>::Target == Rc LL | let _ = Pin::new(Apple) == Rc::pin(Apple); | ^^ expected struct `Apple`, found struct `Rc` | - = note: expected type `Apple` - found type `Rc` + = note: expected struct `Apple` + found struct `Rc` = note: required because of the requirements on the impl of `PartialEq>>` for `Pin` error: aborting due to previous error diff --git a/src/test/ui/never_type/fallback-closure-wrap.fallback.stderr b/src/test/ui/never_type/fallback-closure-wrap.fallback.stderr index 24d45a3062310..78d1a3caf4a30 100644 --- a/src/test/ui/never_type/fallback-closure-wrap.fallback.stderr +++ b/src/test/ui/never_type/fallback-closure-wrap.fallback.stderr @@ -8,8 +8,8 @@ LL | | panic!("Can't connect to server."); LL | | }) as Box); | |______^ expected `()`, found `!` | - = note: expected type `()` - found type `!` + = note: expected unit type `()` + found type `!` = note: required for the cast to the object type `dyn FnMut()` error: aborting due to previous error diff --git a/src/test/ui/traits/associated_type_bound/check-trait-object-bounds-5.stderr b/src/test/ui/traits/associated_type_bound/check-trait-object-bounds-5.stderr index bf7691e7f1b38..4251c1a1ed6cd 100644 --- a/src/test/ui/traits/associated_type_bound/check-trait-object-bounds-5.stderr +++ b/src/test/ui/traits/associated_type_bound/check-trait-object-bounds-5.stderr @@ -4,7 +4,7 @@ error[E0271]: type mismatch resolving `::T == i64` LL | is_obj(x) | ^^^^^^ type mismatch resolving `::T == i64` | -note: expected `i64`, found `i32` +note: expected this to be `i64` --> $DIR/check-trait-object-bounds-5.rs:9:14 | LL | type T = U; diff --git a/src/test/ui/traits/associated_type_bound/check-trait-object-bounds-6.stderr b/src/test/ui/traits/associated_type_bound/check-trait-object-bounds-6.stderr index 016de72847df1..5b23a513eea9b 100644 --- a/src/test/ui/traits/associated_type_bound/check-trait-object-bounds-6.stderr +++ b/src/test/ui/traits/associated_type_bound/check-trait-object-bounds-6.stderr @@ -4,7 +4,7 @@ error[E0271]: type mismatch resolving `::T == i64` LL | is_obj(x) | ^^^^^^ type mismatch resolving `::T == i64` | -note: expected `i64`, found `i32` +note: expected this to be `i64` --> $DIR/check-trait-object-bounds-6.rs:9:14 | LL | type T = U; diff --git a/src/test/ui/type-alias-impl-trait/issue-63355.stderr b/src/test/ui/type-alias-impl-trait/issue-63355.stderr index 860a371b08618..6fc6b4bfe1f00 100644 --- a/src/test/ui/type-alias-impl-trait/issue-63355.stderr +++ b/src/test/ui/type-alias-impl-trait/issue-63355.stderr @@ -1,16 +1,18 @@ error[E0271]: type mismatch resolving `<() as Bar>::Foo == ()` --> $DIR/issue-63355.rs:34:20 | +LL | pub type FooImpl = impl Foo; + | -------- the found opaque type LL | pub type BarImpl = impl Bar; | ^^^^^^^^^^^^^^^^^^^^^^^ type mismatch resolving `<() as Bar>::Foo == ()` | -note: expected `()`, found opaque type +note: expected this to be `()` --> $DIR/issue-63355.rs:24:16 | LL | type Foo = FooImpl; | ^^^^^^^ - = note: expected type `()` - found type `impl Foo` + = note: expected unit type `()` + found opaque type `impl Foo` error: aborting due to previous error diff --git a/src/test/ui/type-alias-impl-trait/issue-89686.stderr b/src/test/ui/type-alias-impl-trait/issue-89686.stderr index 56e6a5420dd30..19ed9a7476c1b 100644 --- a/src/test/ui/type-alias-impl-trait/issue-89686.stderr +++ b/src/test/ui/type-alias-impl-trait/issue-89686.stderr @@ -3,9 +3,17 @@ error[E0271]: type mismatch resolving ` as | LL | type G<'a, T> = impl Future; | ^^^^^^^^^^^^^^^^^^^^^^^^ expected `()`, found associated type +... +LL | async move { self.f().await } + | ------------------ the found `async` block | - = note: expected type `()` - found type ` as Future>::Output` + ::: $SRC_DIR/core/src/future/mod.rs:LL:COL + | +LL | pub const fn from_generator(gen: T) -> impl Future + | ------------------------------- the found opaque type + | + = note: expected unit type `()` + found associated type ` as Future>::Output` = help: consider constraining the associated type ` as Future>::Output` to `()` = note: for more information, visit https://doc.rust-lang.org/book/ch19-03-advanced-traits.html