From 698f8c2f01ea549d77d7dc3338a12e04c11057b9 Mon Sep 17 00:00:00 2001 From: Daniel Baumann Date: Wed, 17 Apr 2024 14:02:58 +0200 Subject: Adding upstream version 1.64.0+dfsg1. Signed-off-by: Daniel Baumann --- compiler/rustc_middle/src/infer/unify_key.rs | 162 +++++++++++++++++++++++++++ 1 file changed, 162 insertions(+) create mode 100644 compiler/rustc_middle/src/infer/unify_key.rs (limited to 'compiler/rustc_middle/src/infer/unify_key.rs') diff --git a/compiler/rustc_middle/src/infer/unify_key.rs b/compiler/rustc_middle/src/infer/unify_key.rs new file mode 100644 index 000000000..f2627885d --- /dev/null +++ b/compiler/rustc_middle/src/infer/unify_key.rs @@ -0,0 +1,162 @@ +use crate::ty::{self, Ty, TyCtxt}; +use rustc_data_structures::unify::{NoError, UnifyKey, UnifyValue}; +use rustc_span::def_id::DefId; +use rustc_span::symbol::Symbol; +use rustc_span::Span; +use std::cmp; +use std::marker::PhantomData; + +pub trait ToType { + fn to_type<'tcx>(&self, tcx: TyCtxt<'tcx>) -> Ty<'tcx>; +} + +#[derive(PartialEq, Copy, Clone, Debug)] +pub struct UnifiedRegion<'tcx>(pub Option>); + +#[derive(PartialEq, Copy, Clone, Debug)] +pub struct RegionVidKey<'tcx> { + pub vid: ty::RegionVid, + pub phantom: PhantomData>, +} + +impl<'tcx> From for RegionVidKey<'tcx> { + fn from(vid: ty::RegionVid) -> Self { + RegionVidKey { vid, phantom: PhantomData } + } +} + +impl<'tcx> UnifyKey for RegionVidKey<'tcx> { + type Value = UnifiedRegion<'tcx>; + #[inline] + fn index(&self) -> u32 { + self.vid.as_u32() + } + #[inline] + fn from_index(i: u32) -> Self { + RegionVidKey::from(ty::RegionVid::from_u32(i)) + } + fn tag() -> &'static str { + "RegionVidKey" + } +} + +impl<'tcx> UnifyValue for UnifiedRegion<'tcx> { + type Error = NoError; + + fn unify_values(value1: &Self, value2: &Self) -> Result { + Ok(match (value1.0, value2.0) { + // Here we can just pick one value, because the full constraints graph + // will be handled later. Ideally, we might want a `MultipleValues` + // variant or something. For now though, this is fine. + (Some(_), Some(_)) => *value1, + + (Some(_), _) => *value1, + (_, Some(_)) => *value2, + + (None, None) => *value1, + }) + } +} + +impl ToType for ty::IntVarValue { + fn to_type<'tcx>(&self, tcx: TyCtxt<'tcx>) -> Ty<'tcx> { + match *self { + ty::IntType(i) => tcx.mk_mach_int(i), + ty::UintType(i) => tcx.mk_mach_uint(i), + } + } +} + +impl ToType for ty::FloatVarValue { + fn to_type<'tcx>(&self, tcx: TyCtxt<'tcx>) -> Ty<'tcx> { + tcx.mk_mach_float(self.0) + } +} + +// Generic consts. + +#[derive(Copy, Clone, Debug)] +pub struct ConstVariableOrigin { + pub kind: ConstVariableOriginKind, + pub span: Span, +} + +/// Reasons to create a const inference variable +#[derive(Copy, Clone, Debug)] +pub enum ConstVariableOriginKind { + MiscVariable, + ConstInference, + ConstParameterDefinition(Symbol, DefId), + SubstitutionPlaceholder, +} + +#[derive(Copy, Clone, Debug)] +pub enum ConstVariableValue<'tcx> { + Known { value: ty::Const<'tcx> }, + Unknown { universe: ty::UniverseIndex }, +} + +impl<'tcx> ConstVariableValue<'tcx> { + /// If this value is known, returns the const it is known to be. + /// Otherwise, `None`. + pub fn known(&self) -> Option> { + match *self { + ConstVariableValue::Unknown { .. } => None, + ConstVariableValue::Known { value } => Some(value), + } + } +} + +#[derive(Copy, Clone, Debug)] +pub struct ConstVarValue<'tcx> { + pub origin: ConstVariableOrigin, + pub val: ConstVariableValue<'tcx>, +} + +impl<'tcx> UnifyKey for ty::ConstVid<'tcx> { + type Value = ConstVarValue<'tcx>; + #[inline] + fn index(&self) -> u32 { + self.index + } + #[inline] + fn from_index(i: u32) -> Self { + ty::ConstVid { index: i, phantom: PhantomData } + } + fn tag() -> &'static str { + "ConstVid" + } +} + +impl<'tcx> UnifyValue for ConstVarValue<'tcx> { + type Error = (ty::Const<'tcx>, ty::Const<'tcx>); + + fn unify_values(&value1: &Self, &value2: &Self) -> Result { + Ok(match (value1.val, value2.val) { + (ConstVariableValue::Known { .. }, ConstVariableValue::Known { .. }) => { + bug!("equating two const variables, both of which have known values") + } + + // If one side is known, prefer that one. + (ConstVariableValue::Known { .. }, ConstVariableValue::Unknown { .. }) => value1, + (ConstVariableValue::Unknown { .. }, ConstVariableValue::Known { .. }) => value2, + + // If both sides are *unknown*, it hardly matters, does it? + ( + ConstVariableValue::Unknown { universe: universe1 }, + ConstVariableValue::Unknown { universe: universe2 }, + ) => { + // If we unify two unbound variables, ?T and ?U, then whatever + // value they wind up taking (which must be the same value) must + // be nameable by both universes. Therefore, the resulting + // universe is the minimum of the two universes, because that is + // the one which contains the fewest names in scope. + let universe = cmp::min(universe1, universe2); + ConstVarValue { + val: ConstVariableValue::Unknown { universe }, + origin: value1.origin, + } + } + }) + } +} -- cgit v1.2.3