diff options
Diffstat (limited to 'compiler')
| -rw-r--r-- | compiler/rustc_feature/src/unstable.rs | 2 | ||||
| -rw-r--r-- | compiler/rustc_hir/src/hir.rs | 13 | ||||
| -rw-r--r-- | compiler/rustc_hir_typeck/src/expr.rs | 66 | ||||
| -rw-r--r-- | compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs | 27 | ||||
| -rw-r--r-- | compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs | 5 | ||||
| -rw-r--r-- | compiler/rustc_hir_typeck/src/intrinsicck.rs | 4 | ||||
| -rw-r--r-- | compiler/rustc_hir_typeck/src/method/suggest.rs | 15 | ||||
| -rw-r--r-- | compiler/rustc_hir_typeck/src/pat.rs | 2 | ||||
| -rw-r--r-- | compiler/rustc_mir_build/src/build/expr/as_rvalue.rs | 2 | ||||
| -rw-r--r-- | compiler/rustc_mir_build/src/build/matches/match_pair.rs | 7 | ||||
| -rw-r--r-- | compiler/rustc_mir_build/src/thir/pattern/mod.rs | 4 | ||||
| -rw-r--r-- | compiler/rustc_pattern_analysis/src/rustc.rs | 11 | ||||
| -rw-r--r-- | compiler/rustc_symbol_mangling/src/v0.rs | 59 | ||||
| -rw-r--r-- | compiler/rustc_trait_selection/src/error_reporting/traits/fulfillment_errors.rs | 39 | ||||
| -rw-r--r-- | compiler/rustc_trait_selection/src/error_reporting/traits/suggestions.rs | 2 | ||||
| -rw-r--r-- | compiler/rustc_trait_selection/src/traits/structural_normalize.rs | 40 |
16 files changed, 186 insertions, 112 deletions
diff --git a/compiler/rustc_feature/src/unstable.rs b/compiler/rustc_feature/src/unstable.rs index 408da6d5d86..0b09e9fbb85 100644 --- a/compiler/rustc_feature/src/unstable.rs +++ b/compiler/rustc_feature/src/unstable.rs @@ -578,7 +578,7 @@ declare_features! ( /// be used to describe E or vise-versa. (unstable, result_ffi_guarantees, "1.80.0", Some(110503)), /// Allows bounding the return type of AFIT/RPITIT. - (incomplete, return_type_notation, "1.70.0", Some(109417)), + (unstable, return_type_notation, "1.70.0", Some(109417)), /// Allows `extern "rust-cold"`. (unstable, rust_cold_cc, "1.63.0", Some(97544)), /// Allows use of x86 SHA512, SM3 and SM4 target-features and intrinsics diff --git a/compiler/rustc_hir/src/hir.rs b/compiler/rustc_hir/src/hir.rs index 17273f1f8fc..71216023ecc 100644 --- a/compiler/rustc_hir/src/hir.rs +++ b/compiler/rustc_hir/src/hir.rs @@ -1668,10 +1668,17 @@ pub enum ArrayLen<'hir> { } impl ArrayLen<'_> { - pub fn hir_id(&self) -> HirId { + pub fn span(self) -> Span { + match self { + ArrayLen::Infer(arg) => arg.span, + ArrayLen::Body(body) => body.span(), + } + } + + pub fn hir_id(self) -> HirId { match self { - ArrayLen::Infer(InferArg { hir_id, .. }) | ArrayLen::Body(ConstArg { hir_id, .. }) => { - *hir_id + ArrayLen::Infer(InferArg { hir_id, .. }) | ArrayLen::Body(&ConstArg { hir_id, .. }) => { + hir_id } } } diff --git a/compiler/rustc_hir_typeck/src/expr.rs b/compiler/rustc_hir_typeck/src/expr.rs index e7efa32bdb0..015a7283250 100644 --- a/compiler/rustc_hir_typeck/src/expr.rs +++ b/compiler/rustc_hir_typeck/src/expr.rs @@ -1491,8 +1491,10 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { expr: &'tcx hir::Expr<'tcx>, ) -> Ty<'tcx> { let tcx = self.tcx; - let count = self.lower_array_length(count); - if let Some(count) = count.try_eval_target_usize(tcx, self.param_env) { + let count_span = count.span(); + let count = self.try_structurally_resolve_const(count_span, self.lower_array_length(count)); + + if let Some(count) = count.try_to_target_usize(tcx) { self.suggest_array_len(expr, count); } @@ -1520,19 +1522,24 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { return Ty::new_error(tcx, guar); } - self.check_repeat_element_needs_copy_bound(element, count, element_ty); + // If the length is 0, we don't create any elements, so we don't copy any. + // If the length is 1, we don't copy that one element, we move it. Only check + // for `Copy` if the length is larger, or unevaluated. + // FIXME(min_const_generic_exprs): We could perhaps defer this check so that + // we don't require `<?0t as Tr>::CONST` doesn't unnecessarily require `Copy`. + if count.try_to_target_usize(tcx).is_none_or(|x| x > 1) { + self.enforce_repeat_element_needs_copy_bound(element, element_ty); + } let ty = Ty::new_array_with_const_len(tcx, t, count); - self.register_wf_obligation(ty.into(), expr.span, ObligationCauseCode::WellFormed(None)); - ty } - fn check_repeat_element_needs_copy_bound( + /// Requires that `element_ty` is `Copy` (unless it's a const expression itself). + fn enforce_repeat_element_needs_copy_bound( &self, element: &hir::Expr<'_>, - count: ty::Const<'tcx>, element_ty: Ty<'tcx>, ) { let tcx = self.tcx; @@ -1565,27 +1572,23 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { _ => traits::IsConstable::No, }; - // If the length is 0, we don't create any elements, so we don't copy any. If the length is 1, we - // don't copy that one element, we move it. Only check for Copy if the length is larger. - if count.try_eval_target_usize(tcx, self.param_env).is_none_or(|len| len > 1) { - let lang_item = self.tcx.require_lang_item(LangItem::Copy, None); - let code = traits::ObligationCauseCode::RepeatElementCopy { - is_constable, - elt_type: element_ty, - elt_span: element.span, - elt_stmt_span: self - .tcx - .hir() - .parent_iter(element.hir_id) - .find_map(|(_, node)| match node { - hir::Node::Item(it) => Some(it.span), - hir::Node::Stmt(stmt) => Some(stmt.span), - _ => None, - }) - .expect("array repeat expressions must be inside an item or statement"), - }; - self.require_type_meets(element_ty, element.span, code, lang_item); - } + let lang_item = self.tcx.require_lang_item(LangItem::Copy, None); + let code = traits::ObligationCauseCode::RepeatElementCopy { + is_constable, + elt_type: element_ty, + elt_span: element.span, + elt_stmt_span: self + .tcx + .hir() + .parent_iter(element.hir_id) + .find_map(|(_, node)| match node { + hir::Node::Item(it) => Some(it.span), + hir::Node::Stmt(stmt) => Some(stmt.span), + _ => None, + }) + .expect("array repeat expressions must be inside an item or statement"), + }; + self.require_type_meets(element_ty, element.span, code, lang_item); } fn check_expr_tuple( @@ -2800,9 +2803,10 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { len: ty::Const<'tcx>, ) { err.span_label(field.span, "unknown field"); - if let (Some(len), Ok(user_index)) = - (len.try_eval_target_usize(self.tcx, self.param_env), field.as_str().parse::<u64>()) - { + if let (Some(len), Ok(user_index)) = ( + self.try_structurally_resolve_const(base.span, len).try_to_target_usize(self.tcx), + field.as_str().parse::<u64>(), + ) { let help = "instead of using tuple indexing, use array indexing"; let applicability = if len < user_index { Applicability::MachineApplicable diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs index 7cae6e08f81..2c469c0d52c 100644 --- a/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs +++ b/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs @@ -1470,6 +1470,33 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { } } + #[instrument(level = "debug", skip(self, sp), ret)] + pub fn try_structurally_resolve_const(&self, sp: Span, ct: ty::Const<'tcx>) -> ty::Const<'tcx> { + // FIXME(min_const_generic_exprs): We could process obligations here if `ct` is a var. + + if self.next_trait_solver() + && let ty::ConstKind::Unevaluated(..) = ct.kind() + { + // We need to use a separate variable here as otherwise the temporary for + // `self.fulfillment_cx.borrow_mut()` is alive in the `Err` branch, resulting + // in a reentrant borrow, causing an ICE. + let result = self + .at(&self.misc(sp), self.param_env) + .structurally_normalize_const(ct, &mut **self.fulfillment_cx.borrow_mut()); + match result { + Ok(normalized_ct) => normalized_ct, + Err(errors) => { + let guar = self.err_ctxt().report_fulfillment_errors(errors); + return ty::Const::new_error(self.tcx, guar); + } + } + } else if self.tcx.features().generic_const_exprs { + ct.normalize(self.tcx, self.param_env) + } else { + ct + } + } + /// Resolves `ty` by a single level if `ty` is a type variable. /// /// When the new solver is enabled, this will also attempt to normalize diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs index b09bd476576..5f89f7dedc2 100644 --- a/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs +++ b/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs @@ -1502,7 +1502,10 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { // Create an dummy type `&[_]` so that both &[] and `&Vec<T>` can coerce to it. let dummy_ty = if let ty::Array(elem_ty, size) = peeled.kind() && let ty::Infer(_) = elem_ty.kind() - && size.try_eval_target_usize(self.tcx, self.param_env) == Some(0) + && self + .try_structurally_resolve_const(provided_expr.span, *size) + .try_to_target_usize(self.tcx) + == Some(0) { let slice = Ty::new_slice(self.tcx, *elem_ty); Ty::new_imm_ref(self.tcx, self.tcx.lifetimes.re_static, slice) diff --git a/compiler/rustc_hir_typeck/src/intrinsicck.rs b/compiler/rustc_hir_typeck/src/intrinsicck.rs index 81d940a3f9b..a4121adf628 100644 --- a/compiler/rustc_hir_typeck/src/intrinsicck.rs +++ b/compiler/rustc_hir_typeck/src/intrinsicck.rs @@ -101,7 +101,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { } } Ok(SizeSkeleton::Generic(size)) => { - if let Some(size) = size.try_eval_target_usize(tcx, self.param_env) { + if let Some(size) = + self.try_structurally_resolve_const(span, size).try_to_target_usize(tcx) + { format!("{size} bytes") } else { format!("generic size {size}") diff --git a/compiler/rustc_hir_typeck/src/method/suggest.rs b/compiler/rustc_hir_typeck/src/method/suggest.rs index 805fb39480c..feb47209f5e 100644 --- a/compiler/rustc_hir_typeck/src/method/suggest.rs +++ b/compiler/rustc_hir_typeck/src/method/suggest.rs @@ -1721,20 +1721,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { } } - if item_name.name == sym::as_str && rcvr_ty.peel_refs().is_str() { - let msg = "remove this method call"; - let mut fallback_span = true; - if let SelfSource::MethodCall(expr) = source { - let call_expr = self.tcx.hir().expect_expr(self.tcx.parent_hir_id(expr.hir_id)); - if let Some(span) = call_expr.span.trim_start(expr.span) { - err.span_suggestion(span, msg, "", Applicability::MachineApplicable); - fallback_span = false; - } - } - if fallback_span { - err.span_label(span, msg); - } - } else if let Some(similar_candidate) = similar_candidate { + if let Some(similar_candidate) = similar_candidate { // Don't emit a suggestion if we found an actual method // that had unsatisfied trait bounds if unsatisfied_predicates.is_empty() diff --git a/compiler/rustc_hir_typeck/src/pat.rs b/compiler/rustc_hir_typeck/src/pat.rs index 51964b8e753..49c5a7d8a65 100644 --- a/compiler/rustc_hir_typeck/src/pat.rs +++ b/compiler/rustc_hir_typeck/src/pat.rs @@ -2412,7 +2412,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { len: ty::Const<'tcx>, min_len: u64, ) -> (Option<Ty<'tcx>>, Ty<'tcx>) { - let len = len.try_eval_target_usize(self.tcx, self.param_env); + let len = self.try_structurally_resolve_const(span, len).try_to_target_usize(self.tcx); let guar = if let Some(len) = len { // Now we know the length... diff --git a/compiler/rustc_mir_build/src/build/expr/as_rvalue.rs b/compiler/rustc_mir_build/src/build/expr/as_rvalue.rs index 5c92791a029..ffedee8a1e8 100644 --- a/compiler/rustc_mir_build/src/build/expr/as_rvalue.rs +++ b/compiler/rustc_mir_build/src/build/expr/as_rvalue.rs @@ -57,7 +57,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { this.in_scope(region_scope, lint_level, |this| this.as_rvalue(block, scope, value)) } ExprKind::Repeat { value, count } => { - if Some(0) == count.try_eval_target_usize(this.tcx, this.param_env) { + if Some(0) == count.try_to_target_usize(this.tcx) { this.build_zero_repeat(block, value, scope, source_info) } else { let value_operand = unpack!( diff --git a/compiler/rustc_mir_build/src/build/matches/match_pair.rs b/compiler/rustc_mir_build/src/build/matches/match_pair.rs index 25151f78c57..6df50057ee8 100644 --- a/compiler/rustc_mir_build/src/build/matches/match_pair.rs +++ b/compiler/rustc_mir_build/src/build/matches/match_pair.rs @@ -42,7 +42,12 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { let tcx = self.tcx; let (min_length, exact_size) = if let Some(place_resolved) = place.try_to_place(self) { match place_resolved.ty(&self.local_decls, tcx).ty.kind() { - ty::Array(_, length) => (length.eval_target_usize(tcx, self.param_env), true), + ty::Array(_, length) => ( + length + .try_to_target_usize(tcx) + .expect("expected len of array pat to be definite"), + true, + ), _ => ((prefix.len() + suffix.len()).try_into().unwrap(), false), } } else { diff --git a/compiler/rustc_mir_build/src/thir/pattern/mod.rs b/compiler/rustc_mir_build/src/thir/pattern/mod.rs index d78e1f5da09..04e921ecc2e 100644 --- a/compiler/rustc_mir_build/src/thir/pattern/mod.rs +++ b/compiler/rustc_mir_build/src/thir/pattern/mod.rs @@ -441,7 +441,9 @@ impl<'a, 'tcx> PatCtxt<'a, 'tcx> { ty::Slice(..) => PatKind::Slice { prefix, slice, suffix }, // Fixed-length array, `[T; len]`. ty::Array(_, len) => { - let len = len.eval_target_usize(self.tcx, self.param_env); + let len = len + .try_to_target_usize(self.tcx) + .expect("expected len of array pat to be definite"); assert!(len >= prefix.len() as u64 + suffix.len() as u64); PatKind::Array { prefix, slice, suffix } } diff --git a/compiler/rustc_pattern_analysis/src/rustc.rs b/compiler/rustc_pattern_analysis/src/rustc.rs index d164b8ab832..72737fb98cb 100644 --- a/compiler/rustc_pattern_analysis/src/rustc.rs +++ b/compiler/rustc_pattern_analysis/src/rustc.rs @@ -352,7 +352,7 @@ impl<'p, 'tcx: 'p> RustcPatCtxt<'p, 'tcx> { ty::Array(sub_ty, len) => { // We treat arrays of a constant but unknown length like slices. ConstructorSet::Slice { - array_len: len.try_eval_target_usize(cx.tcx, cx.param_env).map(|l| l as usize), + array_len: len.try_to_target_usize(cx.tcx).map(|l| l as usize), subtype_is_empty: cx.is_uninhabited(*sub_ty), } } @@ -685,9 +685,12 @@ impl<'p, 'tcx: 'p> RustcPatCtxt<'p, 'tcx> { } PatKind::Array { prefix, slice, suffix } | PatKind::Slice { prefix, slice, suffix } => { let array_len = match ty.kind() { - ty::Array(_, length) => { - Some(length.eval_target_usize(cx.tcx, cx.param_env) as usize) - } + ty::Array(_, length) => Some( + length + .try_to_target_usize(cx.tcx) + .expect("expected len of array pat to be definite") + as usize, + ), ty::Slice(_) => None, _ => span_bug!(pat.span, "bad ty {} for slice pattern", ty.inner()), }; diff --git a/compiler/rustc_symbol_mangling/src/v0.rs b/compiler/rustc_symbol_mangling/src/v0.rs index 79de9bbb351..f3da7ff1ca7 100644 --- a/compiler/rustc_symbol_mangling/src/v0.rs +++ b/compiler/rustc_symbol_mangling/src/v0.rs @@ -607,45 +607,40 @@ impl<'tcx> Printer<'tcx> for SymbolMangler<'tcx> { let _ = write!(self.out, "{bits:x}_"); } + // Handle `str` as partial support for unsized constants + ty::Str => { + let tcx = self.tcx(); + // HACK(jaic1): hide the `str` type behind a reference + // for the following transformation from valtree to raw bytes + let ref_ty = Ty::new_imm_ref(tcx, tcx.lifetimes.re_static, ct_ty); + let slice = valtree.try_to_raw_bytes(tcx, ref_ty).unwrap_or_else(|| { + bug!("expected to get raw bytes from valtree {:?} for type {:}", valtree, ct_ty) + }); + let s = std::str::from_utf8(slice).expect("non utf8 str from MIR interpreter"); + + // "e" for str as a basic type + self.push("e"); + + // FIXME(eddyb) use a specialized hex-encoding loop. + for byte in s.bytes() { + let _ = write!(self.out, "{byte:02x}"); + } + + self.push("_"); + } + // FIXME(valtrees): Remove the special case for `str` // here and fully support unsized constants. - ty::Ref(_, inner_ty, mutbl) => { + ty::Ref(_, _, mutbl) => { self.push(match mutbl { hir::Mutability::Not => "R", hir::Mutability::Mut => "Q", }); - match inner_ty.kind() { - ty::Str if mutbl.is_not() => { - let slice = - valtree.try_to_raw_bytes(self.tcx(), ct_ty).unwrap_or_else(|| { - bug!( - "expected to get raw bytes from valtree {:?} for type {:}", - valtree, - ct_ty - ) - }); - let s = - std::str::from_utf8(slice).expect("non utf8 str from MIR interpreter"); - - self.push("e"); - - // FIXME(eddyb) use a specialized hex-encoding loop. - for byte in s.bytes() { - let _ = write!(self.out, "{byte:02x}"); - } - - self.push("_"); - } - _ => { - let pointee_ty = ct_ty - .builtin_deref(true) - .expect("tried to dereference on non-ptr type"); - let dereferenced_const = - ty::Const::new_value(self.tcx, valtree, pointee_ty); - dereferenced_const.print(self)?; - } - } + let pointee_ty = + ct_ty.builtin_deref(true).expect("tried to dereference on non-ptr type"); + let dereferenced_const = ty::Const::new_value(self.tcx, valtree, pointee_ty); + dereferenced_const.print(self)?; } ty::Array(..) | ty::Tuple(..) | ty::Adt(..) | ty::Slice(_) => { diff --git a/compiler/rustc_trait_selection/src/error_reporting/traits/fulfillment_errors.rs b/compiler/rustc_trait_selection/src/error_reporting/traits/fulfillment_errors.rs index f9aab33d532..19e2679ae4d 100644 --- a/compiler/rustc_trait_selection/src/error_reporting/traits/fulfillment_errors.rs +++ b/compiler/rustc_trait_selection/src/error_reporting/traits/fulfillment_errors.rs @@ -17,7 +17,7 @@ use rustc_middle::traits::SignatureMismatchData; use rustc_middle::traits::select::OverflowError; use rustc_middle::ty::abstract_const::NotConstEvaluatable; use rustc_middle::ty::error::{ExpectedFound, TypeError}; -use rustc_middle::ty::fold::{BottomUpFolder, TypeFolder, TypeSuperFoldable}; +use rustc_middle::ty::fold::{TypeFolder, TypeSuperFoldable}; use rustc_middle::ty::print::{ FmtPrinter, Print, PrintTraitPredicateExt as _, PrintTraitRefExt as _, with_forced_trimmed_paths, @@ -1788,22 +1788,18 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { return false; } - let cand = self.resolve_vars_if_possible(impl_trait_ref).fold_with( - &mut BottomUpFolder { - tcx: self.tcx, - ty_op: |ty| ty, - lt_op: |lt| lt, - ct_op: |ct| ct.normalize(self.tcx, ty::ParamEnv::empty()), - }, - ); - if cand.references_error() { + let impl_trait_ref = self.resolve_vars_if_possible(impl_trait_ref); + if impl_trait_ref.references_error() { return false; } err.highlighted_help(vec![ - StringPart::normal(format!("the trait `{}` ", cand.print_trait_sugared())), + StringPart::normal(format!( + "the trait `{}` ", + impl_trait_ref.print_trait_sugared() + )), StringPart::highlighted("is"), StringPart::normal(" implemented for `"), - StringPart::highlighted(cand.self_ty().to_string()), + StringPart::highlighted(impl_trait_ref.self_ty().to_string()), StringPart::normal("`"), ]); @@ -1915,15 +1911,18 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { let mut impl_candidates: Vec<_> = impl_candidates .iter() .cloned() + .filter(|cand| !cand.trait_ref.references_error()) .map(|mut cand| { - // Fold the consts so that they shows up as, e.g., `10` - // instead of `core::::array::{impl#30}::{constant#0}`. - cand.trait_ref = cand.trait_ref.fold_with(&mut BottomUpFolder { - tcx: self.tcx, - ty_op: |ty| ty, - lt_op: |lt| lt, - ct_op: |ct| ct.normalize(self.tcx, ty::ParamEnv::empty()), - }); + // Normalize the trait ref in its *own* param-env so + // that consts are folded and any trivial projections + // are normalized. + cand.trait_ref = self + .tcx + .try_normalize_erasing_regions( + self.tcx.param_env(cand.impl_def_id), + cand.trait_ref, + ) + .unwrap_or(cand.trait_ref); cand }) .collect(); diff --git a/compiler/rustc_trait_selection/src/error_reporting/traits/suggestions.rs b/compiler/rustc_trait_selection/src/error_reporting/traits/suggestions.rs index 9639d9d319c..6df7fac949c 100644 --- a/compiler/rustc_trait_selection/src/error_reporting/traits/suggestions.rs +++ b/compiler/rustc_trait_selection/src/error_reporting/traits/suggestions.rs @@ -4620,7 +4620,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { format!("&{}{ty}", mutability.prefix_str()) } } - ty::Array(ty, len) if let Some(len) = len.try_eval_target_usize(tcx, param_env) => { + ty::Array(ty, len) if let Some(len) = len.try_to_target_usize(tcx) => { if len == 0 { "[]".to_string() } else if self.type_is_copy_modulo_regions(param_env, ty) || len == 1 { diff --git a/compiler/rustc_trait_selection/src/traits/structural_normalize.rs b/compiler/rustc_trait_selection/src/traits/structural_normalize.rs index 9d657ade86b..3814f8112e9 100644 --- a/compiler/rustc_trait_selection/src/traits/structural_normalize.rs +++ b/compiler/rustc_trait_selection/src/traits/structural_normalize.rs @@ -46,4 +46,44 @@ impl<'tcx> At<'_, 'tcx> { Ok(self.normalize(ty).into_value_registering_obligations(self.infcx, fulfill_cx)) } } + + fn structurally_normalize_const<E: 'tcx>( + &self, + ct: ty::Const<'tcx>, + fulfill_cx: &mut dyn TraitEngine<'tcx, E>, + ) -> Result<ty::Const<'tcx>, Vec<E>> { + assert!(!ct.is_ct_infer(), "should have resolved vars before calling"); + + if self.infcx.next_trait_solver() { + let ty::ConstKind::Unevaluated(..) = ct.kind() else { + return Ok(ct); + }; + + let new_infer_ct = self.infcx.next_const_var(self.cause.span); + + // We simply emit an `alias-eq` goal here, since that will take care of + // normalizing the LHS of the projection until it is a rigid projection + // (or a not-yet-defined opaque in scope). + let obligation = Obligation::new( + self.infcx.tcx, + self.cause.clone(), + self.param_env, + ty::PredicateKind::AliasRelate( + ct.into(), + new_infer_ct.into(), + ty::AliasRelationDirection::Equate, + ), + ); + + fulfill_cx.register_predicate_obligation(self.infcx, obligation); + let errors = fulfill_cx.select_where_possible(self.infcx); + if !errors.is_empty() { + return Err(errors); + } + + Ok(self.infcx.resolve_vars_if_possible(new_infer_ct)) + } else { + Ok(self.normalize(ct).into_value_registering_obligations(self.infcx, fulfill_cx)) + } + } } |
