Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Rollup of 7 pull requests #135835

Closed
wants to merge 16 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,7 @@ __pycache__/
node_modules
package-lock.json
package.json
/src/doc/rustc-dev-guide/mermaid.min.js

## Rustdoc GUI tests
tests/rustdoc-gui/src/**.lock
Expand Down
4 changes: 2 additions & 2 deletions compiler/rustc_borrowck/src/type_check/canonical.rs
Original file line number Diff line number Diff line change
Expand Up @@ -185,7 +185,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
CustomTypeOp::new(
|ocx| {
let structurally_normalize = |ty| {
ocx.structurally_normalize(
ocx.structurally_normalize_ty(
&ObligationCause::misc(
location.to_locations().span(body),
body.source.def_id().expect_local(),
Expand Down Expand Up @@ -230,7 +230,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
ConstraintCategory::Boring,
CustomTypeOp::new(
|ocx| {
ocx.structurally_normalize(
ocx.structurally_normalize_ty(
&ObligationCause::misc(
location.to_locations().span(body),
body.source.def_id().expect_local(),
Expand Down
8 changes: 4 additions & 4 deletions compiler/rustc_hir_analysis/src/autoderef.rs
Original file line number Diff line number Diff line change
Expand Up @@ -86,7 +86,7 @@ impl<'a, 'tcx> Iterator for Autoderef<'a, 'tcx> {
if self.infcx.next_trait_solver()
&& let ty::Alias(..) = ty.kind()
{
let (normalized_ty, obligations) = self.structurally_normalize(ty)?;
let (normalized_ty, obligations) = self.structurally_normalize_ty(ty)?;
self.state.obligations.extend(obligations);
(AutoderefKind::Builtin, normalized_ty)
} else {
Expand Down Expand Up @@ -166,20 +166,20 @@ impl<'a, 'tcx> Autoderef<'a, 'tcx> {
}

let (normalized_ty, obligations) =
self.structurally_normalize(Ty::new_projection(tcx, trait_target_def_id, [ty]))?;
self.structurally_normalize_ty(Ty::new_projection(tcx, trait_target_def_id, [ty]))?;
debug!("overloaded_deref_ty({:?}) = ({:?}, {:?})", ty, normalized_ty, obligations);
self.state.obligations.extend(obligations);

Some(self.infcx.resolve_vars_if_possible(normalized_ty))
}

#[instrument(level = "debug", skip(self), ret)]
pub fn structurally_normalize(
pub fn structurally_normalize_ty(
&self,
ty: Ty<'tcx>,
) -> Option<(Ty<'tcx>, PredicateObligations<'tcx>)> {
let ocx = ObligationCtxt::new(self.infcx);
let Ok(normalized_ty) = ocx.structurally_normalize(
let Ok(normalized_ty) = ocx.structurally_normalize_ty(
&traits::ObligationCause::misc(self.span, self.body_id),
self.param_env,
ty,
Expand Down
2 changes: 1 addition & 1 deletion compiler/rustc_hir_analysis/src/coherence/orphan.rs
Original file line number Diff line number Diff line change
Expand Up @@ -320,7 +320,7 @@ fn orphan_check<'tcx>(
}

let ty = if infcx.next_trait_solver() {
ocx.structurally_normalize(
ocx.structurally_normalize_ty(
&cause,
ty::ParamEnv::empty(),
infcx.resolve_vars_if_possible(ty),
Expand Down
2 changes: 1 addition & 1 deletion compiler/rustc_hir_typeck/src/coercion.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1124,7 +1124,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
if self.next_trait_solver()
&& let ty::Alias(..) = ty.kind()
{
ocx.structurally_normalize(&cause, self.param_env, ty)
ocx.structurally_normalize_ty(&cause, self.param_env, ty)
} else {
Ok(ty)
}
Expand Down
2 changes: 1 addition & 1 deletion compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1433,7 +1433,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
// in a reentrant borrow, causing an ICE.
let result = self
.at(&self.misc(sp), self.param_env)
.structurally_normalize(ty, &mut **self.fulfillment_cx.borrow_mut());
.structurally_normalize_ty(ty, &mut **self.fulfillment_cx.borrow_mut());
match result {
Ok(normalized_ty) => normalized_ty,
Err(errors) => {
Expand Down
42 changes: 19 additions & 23 deletions compiler/rustc_next_trait_solver/src/solve/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -277,23 +277,7 @@ where
param_env: I::ParamEnv,
ty: I::Ty,
) -> Result<I::Ty, NoSolution> {
if let ty::Alias(..) = ty.kind() {
let normalized_ty = self.next_ty_infer();
let alias_relate_goal = Goal::new(
self.cx(),
param_env,
ty::PredicateKind::AliasRelate(
ty.into(),
normalized_ty.into(),
ty::AliasRelationDirection::Equate,
),
);
self.add_goal(GoalSource::Misc, alias_relate_goal);
self.try_evaluate_added_goals()?;
Ok(self.resolve_vars_if_possible(normalized_ty))
} else {
Ok(ty)
}
self.structurally_normalize_term(param_env, ty.into()).map(|term| term.expect_ty())
}

/// Normalize a const for when it is structurally matched on, or more likely
Expand All @@ -308,22 +292,34 @@ where
param_env: I::ParamEnv,
ct: I::Const,
) -> Result<I::Const, NoSolution> {
if let ty::ConstKind::Unevaluated(..) = ct.kind() {
let normalized_ct = self.next_const_infer();
self.structurally_normalize_term(param_env, ct.into()).map(|term| term.expect_const())
}

/// Normalize a term for when it is structurally matched on.
///
/// This function is necessary in nearly all cases before matching on a ty/const.
/// Not doing so is likely to be incomplete and therefore unsound during coherence.
fn structurally_normalize_term(
&mut self,
param_env: I::ParamEnv,
term: I::Term,
) -> Result<I::Term, NoSolution> {
if let Some(_) = term.to_alias_term() {
let normalized_term = self.next_term_infer_of_kind(term);
let alias_relate_goal = Goal::new(
self.cx(),
param_env,
ty::PredicateKind::AliasRelate(
ct.into(),
normalized_ct.into(),
term,
normalized_term,
ty::AliasRelationDirection::Equate,
),
);
self.add_goal(GoalSource::Misc, alias_relate_goal);
self.try_evaluate_added_goals()?;
Ok(self.resolve_vars_if_possible(normalized_ct))
Ok(self.resolve_vars_if_possible(normalized_term))
} else {
Ok(ct)
Ok(term)
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1338,20 +1338,15 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
let derive_better_type_error =
|alias_term: ty::AliasTerm<'tcx>, expected_term: ty::Term<'tcx>| {
let ocx = ObligationCtxt::new(self);
let normalized_term = match expected_term.unpack() {
ty::TermKind::Ty(_) => self.next_ty_var(DUMMY_SP).into(),
ty::TermKind::Const(_) => self.next_const_var(DUMMY_SP).into(),
};
ocx.register_obligation(Obligation::new(
self.tcx,
ObligationCause::dummy(),

let Ok(normalized_term) = ocx.structurally_normalize_term(
&ObligationCause::dummy(),
obligation.param_env,
ty::PredicateKind::NormalizesTo(ty::NormalizesTo {
alias: alias_term,
term: normalized_term,
}),
));
let _ = ocx.select_where_possible();
alias_term.to_term(self.tcx),
) else {
return None;
};

if let Err(terr) = ocx.eq(
&ObligationCause::dummy(),
obligation.param_env,
Expand Down
2 changes: 1 addition & 1 deletion compiler/rustc_trait_selection/src/traits/coherence.rs
Original file line number Diff line number Diff line change
Expand Up @@ -709,7 +709,7 @@ impl<'a, 'tcx> ProofTreeVisitor<'tcx> for AmbiguityCausesVisitor<'a, 'tcx> {
if matches!(ty.kind(), ty::Alias(..)) {
let ocx = ObligationCtxt::new(infcx);
ty = ocx
.structurally_normalize(&ObligationCause::dummy(), param_env, ty)
.structurally_normalize_ty(&ObligationCause::dummy(), param_env, ty)
.map_err(|_| ())?;
if !ocx.select_where_possible().is_empty() {
return Err(());
Expand Down
15 changes: 13 additions & 2 deletions compiler/rustc_trait_selection/src/traits/engine.rs
Original file line number Diff line number Diff line change
Expand Up @@ -319,15 +319,15 @@ where
self.infcx.at(cause, param_env).deeply_normalize(value, &mut **self.engine.borrow_mut())
}

pub fn structurally_normalize(
pub fn structurally_normalize_ty(
&self,
cause: &ObligationCause<'tcx>,
param_env: ty::ParamEnv<'tcx>,
value: Ty<'tcx>,
) -> Result<Ty<'tcx>, Vec<E>> {
self.infcx
.at(cause, param_env)
.structurally_normalize(value, &mut **self.engine.borrow_mut())
.structurally_normalize_ty(value, &mut **self.engine.borrow_mut())
}

pub fn structurally_normalize_const(
Expand All @@ -340,4 +340,15 @@ where
.at(cause, param_env)
.structurally_normalize_const(value, &mut **self.engine.borrow_mut())
}

pub fn structurally_normalize_term(
&self,
cause: &ObligationCause<'tcx>,
param_env: ty::ParamEnv<'tcx>,
value: ty::Term<'tcx>,
) -> Result<ty::Term<'tcx>, Vec<E>> {
self.infcx
.at(cause, param_env)
.structurally_normalize_term(value, &mut **self.engine.borrow_mut())
}
}
73 changes: 25 additions & 48 deletions compiler/rustc_trait_selection/src/traits/structural_normalize.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,59 +7,42 @@ use crate::traits::{NormalizeExt, Obligation};

#[extension(pub trait StructurallyNormalizeExt<'tcx>)]
impl<'tcx> At<'_, 'tcx> {
fn structurally_normalize<E: 'tcx>(
fn structurally_normalize_ty<E: 'tcx>(
&self,
ty: Ty<'tcx>,
fulfill_cx: &mut dyn TraitEngine<'tcx, E>,
) -> Result<Ty<'tcx>, Vec<E>> {
assert!(!ty.is_ty_var(), "should have resolved vars before calling");

if self.infcx.next_trait_solver() {
let ty::Alias(..) = *ty.kind() else {
return Ok(ty);
};

let new_infer_ty = self.infcx.next_ty_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(
ty.into(),
new_infer_ty.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_ty))
} else {
Ok(self.normalize(ty).into_value_registering_obligations(self.infcx, fulfill_cx))
}
self.structurally_normalize_term(ty.into(), fulfill_cx).map(|term| term.expect_type())
}

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.tcx.features().generic_const_exprs() {
return Ok(super::evaluate_const(&self.infcx, ct, self.param_env));
}

self.structurally_normalize_term(ct.into(), fulfill_cx).map(|term| term.expect_const())
}

fn structurally_normalize_term<E: 'tcx>(
&self,
term: ty::Term<'tcx>,
fulfill_cx: &mut dyn TraitEngine<'tcx, E>,
) -> Result<ty::Term<'tcx>, Vec<E>> {
assert!(!term.is_infer(), "should have resolved vars before calling");

if self.infcx.next_trait_solver() {
let ty::ConstKind::Unevaluated(..) = ct.kind() else {
return Ok(ct);
};
if let None = term.to_alias_term() {
return Ok(term);
}

let new_infer_ct = self.infcx.next_const_var(self.cause.span);
let new_infer = match term.unpack() {
ty::TermKind::Ty(_) => self.infcx.next_ty_var(self.cause.span).into(),
ty::TermKind::Const(_) => self.infcx.next_const_var(self.cause.span).into(),
};

// 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
Expand All @@ -68,11 +51,7 @@ impl<'tcx> At<'_, 'tcx> {
self.infcx.tcx,
self.cause.clone(),
self.param_env,
ty::PredicateKind::AliasRelate(
ct.into(),
new_infer_ct.into(),
ty::AliasRelationDirection::Equate,
),
ty::PredicateKind::AliasRelate(term, new_infer, ty::AliasRelationDirection::Equate),
);

fulfill_cx.register_predicate_obligation(self.infcx, obligation);
Expand All @@ -81,11 +60,9 @@ impl<'tcx> At<'_, 'tcx> {
return Err(errors);
}

Ok(self.infcx.resolve_vars_if_possible(new_infer_ct))
} else if self.infcx.tcx.features().generic_const_exprs() {
Ok(super::evaluate_const(&self.infcx, ct, self.param_env))
Ok(self.infcx.resolve_vars_if_possible(new_infer))
} else {
Ok(self.normalize(ct).into_value_registering_obligations(self.infcx, fulfill_cx))
Ok(self.normalize(term).into_value_registering_obligations(self.infcx, fulfill_cx))
}
}
}
11 changes: 11 additions & 0 deletions library/core/src/macros/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -313,6 +313,17 @@ pub macro cfg_match {
/// }
/// }
/// ```
///
/// If desired, it is possible to return expressions through the use of surrounding braces:
///
/// ```
/// #![feature(cfg_match)]
///
/// let _some_string = cfg_match! {{
/// unix => { "With great power comes great electricity bills" },
/// _ => { "Behind every successful diet is an unwatched pizza" },
/// }};
/// ```
#[cfg(not(bootstrap))]
#[unstable(feature = "cfg_match", issue = "115585")]
#[rustc_diagnostic_item = "cfg_match"]
Expand Down
33 changes: 31 additions & 2 deletions library/core/src/num/uint_macros.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2663,8 +2663,8 @@ macro_rules! uint_impl {
///
/// Basic usage:
///
/// Please note that this example is shared between integer types.
/// Which explains why `u32` is used here.
/// Please note that this example is shared between integer types,
/// which explains why `u32` is used here.
///
/// ```
/// #![feature(bigint_helper_methods)]
Expand All @@ -2677,6 +2677,35 @@ macro_rules! uint_impl {
"(", stringify!($SelfT), "::MAX, ", stringify!($SelfT), "::MAX));"
)]
/// ```
///
/// This is the core per-digit operation for "grade school" O(n²) multiplication.
///
/// Please note that this example is shared between integer types,
/// using `u8` for simplicity of the demonstration.
///
/// ```
/// #![feature(bigint_helper_methods)]
///
/// fn quadratic_mul<const N: usize>(a: [u8; N], b: [u8; N]) -> [u8; N] {
/// let mut out = [0; N];
/// for j in 0..N {
/// let mut carry = 0;
/// for i in 0..(N - j) {
/// (out[j + i], carry) = u8::carrying_mul_add(a[i], b[j], out[j + i], carry);
/// }
/// }
/// out
/// }
///
/// // -1 * -1 == 1
/// assert_eq!(quadratic_mul([0xFF; 3], [0xFF; 3]), [1, 0, 0]);
///
/// assert_eq!(u32::wrapping_mul(0x9e3779b9, 0x7f4a7c15), 0xCFFC982D);
/// assert_eq!(
/// quadratic_mul(u32::to_le_bytes(0x9e3779b9), u32::to_le_bytes(0x7f4a7c15)),
/// u32::to_le_bytes(0xCFFC982D)
/// );
/// ```
#[unstable(feature = "bigint_helper_methods", issue = "85532")]
#[rustc_const_unstable(feature = "bigint_helper_methods", issue = "85532")]
#[must_use = "this returns the result of the operation, \
Expand Down
Loading
Loading