Auto merge of #126108 - workingjubilee:rollup-g7m92b6, r=workingjubilee

Rollup of 7 pull requests

Successful merges:

 - #125606 (Size optimize int formatting)
 - #125724 (Uplift `Relate`/`TypeRelation` into `rustc_next_trait_solver`)
 - #126040 (Don't warn on fields in the `unreachable_pub` lint )
 - #126098 (Remove `same-lib-two-locations-no-panic` run-make test)
 - #126099 (Crate loader cleanups)
 - #126101 (Revert "Disallow ambiguous attributes on expressions" on nightly)
 - #126103 (Improve Docs for `hir::Impl` and `hir::ImplItem`)

r? `@ghost`
`@rustbot` modify labels: rollup
This commit is contained in:
bors 2024-06-07 06:49:55 +00:00
commit 468310ea0c
77 changed files with 1488 additions and 1308 deletions

View file

@ -4201,6 +4201,7 @@ dependencies = [
"rustc_middle",
"rustc_span",
"rustc_target",
"rustc_type_ir",
"smallvec",
"tracing",
]
@ -4392,7 +4393,6 @@ dependencies = [
"rustc_hir_pretty",
"rustc_index",
"rustc_macros",
"rustc_next_trait_solver",
"rustc_query_system",
"rustc_serialize",
"rustc_session",
@ -4509,6 +4509,7 @@ dependencies = [
"rustc_serialize",
"rustc_type_ir",
"rustc_type_ir_macros",
"tracing",
]
[[package]]

View file

@ -1,7 +1,7 @@
use rustc_data_structures::graph::scc::Sccs;
use rustc_index::{IndexSlice, IndexVec};
use rustc_middle::mir::ConstraintCategory;
use rustc_middle::ty::{RegionVid, VarianceDiagInfo};
use rustc_middle::ty::{RegionVid, TyCtxt, VarianceDiagInfo};
use rustc_span::Span;
use std::fmt;
use std::ops::Index;
@ -97,7 +97,7 @@ pub struct OutlivesConstraint<'tcx> {
pub category: ConstraintCategory<'tcx>,
/// Variance diagnostic information
pub variance_info: VarianceDiagInfo<'tcx>,
pub variance_info: VarianceDiagInfo<TyCtxt<'tcx>>,
/// If this constraint is promoted from closure requirements.
pub from_closure: bool,

View file

@ -2304,5 +2304,5 @@ pub struct BlameConstraint<'tcx> {
pub category: ConstraintCategory<'tcx>,
pub from_closure: bool,
pub cause: ObligationCause<'tcx>,
pub variance_info: ty::VarianceDiagInfo<'tcx>,
pub variance_info: ty::VarianceDiagInfo<TyCtxt<'tcx>>,
}

View file

@ -1,14 +1,14 @@
use rustc_data_structures::fx::FxHashMap;
use rustc_errors::ErrorGuaranteed;
use rustc_infer::infer::relate::{ObligationEmittingRelation, StructurallyRelateAliases};
use rustc_infer::infer::relate::{Relate, RelateResult, TypeRelation};
use rustc_infer::infer::NllRegionVariableOrigin;
use rustc_infer::infer::{ObligationEmittingRelation, StructurallyRelateAliases};
use rustc_infer::traits::{Obligation, PredicateObligations};
use rustc_middle::mir::ConstraintCategory;
use rustc_middle::span_bug;
use rustc_middle::traits::query::NoSolution;
use rustc_middle::traits::ObligationCause;
use rustc_middle::ty::fold::FnMutDelegate;
use rustc_middle::ty::relate::{Relate, RelateResult, TypeRelation};
use rustc_middle::ty::{self, Ty, TyCtxt, TypeVisitableExt};
use rustc_span::symbol::sym;
use rustc_span::{Span, Symbol};
@ -82,7 +82,7 @@ pub struct NllTypeRelating<'me, 'bccx, 'tcx> {
/// - Bivariant means that it doesn't matter.
ambient_variance: ty::Variance,
ambient_variance_info: ty::VarianceDiagInfo<'tcx>,
ambient_variance_info: ty::VarianceDiagInfo<TyCtxt<'tcx>>,
}
impl<'me, 'bccx, 'tcx> NllTypeRelating<'me, 'bccx, 'tcx> {
@ -296,7 +296,7 @@ fn push_outlives(
&mut self,
sup: ty::Region<'tcx>,
sub: ty::Region<'tcx>,
info: ty::VarianceDiagInfo<'tcx>,
info: ty::VarianceDiagInfo<TyCtxt<'tcx>>,
) {
let sub = self.type_checker.borrowck_context.universal_regions.to_region_vid(sub);
let sup = self.type_checker.borrowck_context.universal_regions.to_region_vid(sup);
@ -314,7 +314,7 @@ fn push_outlives(
}
}
impl<'bccx, 'tcx> TypeRelation<'tcx> for NllTypeRelating<'_, 'bccx, 'tcx> {
impl<'bccx, 'tcx> TypeRelation<TyCtxt<'tcx>> for NllTypeRelating<'_, 'bccx, 'tcx> {
fn tcx(&self) -> TyCtxt<'tcx> {
self.type_checker.infcx.tcx
}
@ -324,10 +324,10 @@ fn tag(&self) -> &'static str {
}
#[instrument(skip(self, info), level = "trace", ret)]
fn relate_with_variance<T: Relate<'tcx>>(
fn relate_with_variance<T: Relate<TyCtxt<'tcx>>>(
&mut self,
variance: ty::Variance,
info: ty::VarianceDiagInfo<'tcx>,
info: ty::VarianceDiagInfo<TyCtxt<'tcx>>,
a: T,
b: T,
) -> RelateResult<'tcx, T> {
@ -445,7 +445,7 @@ fn binders<T>(
b: ty::Binder<'tcx, T>,
) -> RelateResult<'tcx, ty::Binder<'tcx, T>>
where
T: Relate<'tcx>,
T: Relate<TyCtxt<'tcx>>,
{
// We want that
//

View file

@ -2345,7 +2345,9 @@ pub fn hir_id(&self) -> HirId {
}
}
/// Represents anything within an `impl` block.
/// Represents an associated item within an impl block.
///
/// Refer to [`Impl`] for an impl block declaration.
#[derive(Debug, Clone, Copy, HashStable_Generic)]
pub struct ImplItem<'hir> {
pub ident: Ident,
@ -3327,6 +3329,10 @@ pub enum ItemKind<'hir> {
Impl(&'hir Impl<'hir>),
}
/// Represents an impl block declaration.
///
/// E.g., `impl $Type { .. }` or `impl $Trait for $Type { .. }`
/// Refer to [`ImplItem`] for an associated item within an impl block.
#[derive(Debug, Clone, Copy, HashStable_Generic)]
pub struct Impl<'hir> {
pub safety: Safety,

View file

@ -15,6 +15,7 @@
use rustc_middle::middle::resolve_bound_vars::ResolvedArg;
use rustc_middle::middle::stability::EvalResult;
use rustc_middle::span_bug;
use rustc_middle::ty::error::TypeErrorToStringExt;
use rustc_middle::ty::fold::BottomUpFolder;
use rustc_middle::ty::layout::{LayoutError, MAX_SIMD_LANES};
use rustc_middle::ty::util::{Discr, InspectCoroutineFields, IntTypeExt};

View file

@ -41,6 +41,7 @@
use rustc_hir as hir;
use rustc_hir::def_id::{DefId, LocalDefId};
use rustc_hir_analysis::hir_ty_lowering::HirTyLowerer;
use rustc_infer::infer::relate::RelateResult;
use rustc_infer::infer::{Coercion, DefineOpaqueTypes, InferOk, InferResult};
use rustc_infer::traits::{IfExpressionCause, MatchExpressionArmCause};
use rustc_infer::traits::{Obligation, PredicateObligation};
@ -51,7 +52,6 @@
Adjust, Adjustment, AllowTwoPhase, AutoBorrow, AutoBorrowMutability, PointerCoercion,
};
use rustc_middle::ty::error::TypeError;
use rustc_middle::ty::relate::RelateResult;
use rustc_middle::ty::visit::TypeVisitableExt;
use rustc_middle::ty::{self, GenericArgsRef, Ty, TyCtxt};
use rustc_session::parse::feature_err;

View file

@ -40,7 +40,7 @@
use rustc_infer::traits::query::NoSolution;
use rustc_infer::traits::ObligationCause;
use rustc_middle::ty::adjustment::{Adjust, Adjustment, AllowTwoPhase};
use rustc_middle::ty::error::{ExpectedFound, TypeError::Sorts};
use rustc_middle::ty::error::{ExpectedFound, TypeError};
use rustc_middle::ty::GenericArgsRef;
use rustc_middle::ty::{self, AdtKind, Ty, TypeVisitableExt};
use rustc_middle::{bug, span_bug};
@ -682,7 +682,8 @@ fn check_expr_break(
self.suggest_mismatched_types_on_tail(
&mut err, expr, ty, e_ty, target_id,
);
let error = Some(Sorts(ExpectedFound { expected: ty, found: e_ty }));
let error =
Some(TypeError::Sorts(ExpectedFound { expected: ty, found: e_ty }));
self.annotate_loop_expected_due_to_inference(err, expr, error);
if let Some(val) =
self.err_ctxt().ty_kind_suggestion(self.param_env, ty)

View file

@ -18,6 +18,7 @@ rustc_macros = { path = "../rustc_macros" }
rustc_middle = { path = "../rustc_middle" }
rustc_span = { path = "../rustc_span" }
rustc_target = { path = "../rustc_target" }
rustc_type_ir = { path = "../rustc_type_ir" }
smallvec = { version = "1.8.1", features = ["union", "may_dangle"] }
tracing = "0.1"
# tidy-alphabetical-end

View file

@ -27,8 +27,8 @@
use super::*;
use crate::infer::relate::{Relate, StructurallyRelateAliases, TypeRelation};
use rustc_middle::bug;
use rustc_middle::ty::relate::{Relate, TypeRelation};
use rustc_middle::ty::{Const, ImplSubject};
/// Whether we should define opaque types or just treat them opaquely.
@ -90,7 +90,7 @@ pub fn fork_with_intercrate(&self, intercrate: bool) -> Self {
}
}
pub trait ToTrace<'tcx>: Relate<'tcx> + Copy {
pub trait ToTrace<'tcx>: Relate<TyCtxt<'tcx>> + Copy {
fn to_trace(
cause: &ObligationCause<'tcx>,
a_is_expected: bool,

View file

@ -58,6 +58,7 @@
PredicateObligation,
};
use crate::infer::relate::{self, RelateResult, TypeRelation};
use rustc_data_structures::fx::{FxIndexMap, FxIndexSet};
use rustc_errors::{
codes::*, pluralize, struct_span_code_err, Applicability, Diag, DiagCtxt, DiagStyledString,
@ -71,8 +72,8 @@
use rustc_macros::extension;
use rustc_middle::bug;
use rustc_middle::dep_graph::DepContext;
use rustc_middle::ty::error::TypeErrorToStringExt;
use rustc_middle::ty::print::{with_forced_trimmed_paths, PrintError, PrintTraitRefExt as _};
use rustc_middle::ty::relate::{self, RelateResult, TypeRelation};
use rustc_middle::ty::Upcast;
use rustc_middle::ty::{
self, error::TypeError, IsSuggestable, List, Region, Ty, TyCtxt, TypeFoldable,
@ -2686,7 +2687,7 @@ pub fn is_try_conversion(&self, span: Span, trait_def_id: DefId) -> bool {
/// with the other type. A TyVar inference type is compatible with any type, and an IntVar or
/// FloatVar inference type are compatible with themselves or their concrete types (Int and
/// Float types, respectively). When comparing two ADTs, these rules apply recursively.
pub fn same_type_modulo_infer<T: relate::Relate<'tcx>>(&self, a: T, b: T) -> bool {
pub fn same_type_modulo_infer<T: relate::Relate<TyCtxt<'tcx>>>(&self, a: T, b: T) -> bool {
let (a, b) = self.resolve_vars_if_possible((a, b));
SameTypeModuloInfer(self).relate(a, b).is_ok()
}
@ -2694,7 +2695,7 @@ pub fn same_type_modulo_infer<T: relate::Relate<'tcx>>(&self, a: T, b: T) -> boo
struct SameTypeModuloInfer<'a, 'tcx>(&'a InferCtxt<'tcx>);
impl<'tcx> TypeRelation<'tcx> for SameTypeModuloInfer<'_, 'tcx> {
impl<'tcx> TypeRelation<TyCtxt<'tcx>> for SameTypeModuloInfer<'_, 'tcx> {
fn tcx(&self) -> TyCtxt<'tcx> {
self.0.tcx
}
@ -2703,10 +2704,10 @@ fn tag(&self) -> &'static str {
"SameTypeModuloInfer"
}
fn relate_with_variance<T: relate::Relate<'tcx>>(
fn relate_with_variance<T: relate::Relate<TyCtxt<'tcx>>>(
&mut self,
_variance: ty::Variance,
_info: ty::VarianceDiagInfo<'tcx>,
_info: ty::VarianceDiagInfo<TyCtxt<'tcx>>,
a: T,
b: T,
) -> relate::RelateResult<'tcx, T> {
@ -2754,7 +2755,7 @@ fn binders<T>(
b: ty::Binder<'tcx, T>,
) -> relate::RelateResult<'tcx, ty::Binder<'tcx, T>>
where
T: relate::Relate<'tcx>,
T: relate::Relate<TyCtxt<'tcx>>,
{
Ok(a.rebind(self.relate(a.skip_binder(), b.skip_binder())?))
}

View file

@ -21,13 +21,12 @@ pub fn note_and_explain_type_err(
sp: Span,
body_owner_def_id: DefId,
) {
use ty::error::TypeError::*;
debug!("note_and_explain_type_err err={:?} cause={:?}", err, cause);
let tcx = self.tcx;
match err {
ArgumentSorts(values, _) | Sorts(values) => {
TypeError::ArgumentSorts(values, _) | TypeError::Sorts(values) => {
match (*values.expected.kind(), *values.found.kind()) {
(ty::Closure(..), ty::Closure(..)) => {
diag.note("no two closures, even if identical, have the same type");
@ -483,7 +482,7 @@ fn foo(&self, x: T) -> T { x }
values.found.kind(),
);
}
CyclicTy(ty) => {
TypeError::CyclicTy(ty) => {
// Watch out for various cases of cyclic types and try to explain.
if ty.is_closure() || ty.is_coroutine() || ty.is_coroutine_closure() {
diag.note(
@ -494,7 +493,7 @@ fn foo(&self, x: T) -> T { x }
);
}
}
TargetFeatureCast(def_id) => {
TypeError::TargetFeatureCast(def_id) => {
let target_spans = tcx.get_attrs(def_id, sym::target_feature).map(|attr| attr.span);
diag.note(
"functions with `#[target_feature]` can only be coerced to `unsafe` function pointers"

View file

@ -1,9 +1,6 @@
pub use at::DefineOpaqueTypes;
pub use freshen::TypeFreshener;
pub use lexical_region_resolve::RegionResolutionError;
pub use relate::combine::CombineFields;
pub use relate::combine::ObligationEmittingRelation;
pub use relate::StructurallyRelateAliases;
pub use rustc_macros::{TypeFoldable, TypeVisitable};
pub use rustc_middle::ty::IntVarValue;
pub use BoundRegionConversionTime::*;
@ -11,6 +8,7 @@
pub use SubregionOrigin::*;
pub use ValuePairs::*;
use crate::infer::relate::{CombineFields, RelateResult};
use crate::traits::{
self, ObligationCause, ObligationInspector, PredicateObligations, TraitEngine,
};
@ -39,7 +37,6 @@
use rustc_middle::ty::error::{ExpectedFound, TypeError};
use rustc_middle::ty::fold::BoundVarReplacerDelegate;
use rustc_middle::ty::fold::{TypeFoldable, TypeFolder, TypeSuperFoldable};
use rustc_middle::ty::relate::RelateResult;
use rustc_middle::ty::visit::TypeVisitableExt;
use rustc_middle::ty::{self, GenericParamDefKind, InferConst, Ty, TyCtxt};
use rustc_middle::ty::{ConstVid, EffectVid, FloatVid, IntVid, TyVid};
@ -62,7 +59,7 @@
pub mod outlives;
mod projection;
pub mod region_constraints;
mod relate;
pub mod relate;
pub mod resolve;
pub(crate) mod snapshot;
pub mod type_variable;

View file

@ -1,15 +1,12 @@
use std::collections::hash_map::Entry;
use rustc_data_structures::fx::FxHashMap;
use rustc_middle::ty::error::TypeError;
use rustc_middle::ty::TypeVisitableExt;
use rustc_middle::ty::{
self,
error::TypeError,
relate::{self, Relate, RelateResult, TypeRelation},
Ty, TyCtxt,
};
use rustc_middle::ty::{self, Ty, TyCtxt};
use crate::infer::region_constraints::VerifyIfEq;
use crate::infer::relate::{self as relate, Relate, RelateResult, TypeRelation};
/// Given a "verify-if-eq" type test like:
///
@ -135,7 +132,7 @@ fn bind(
}
}
impl<'tcx> TypeRelation<'tcx> for MatchAgainstHigherRankedOutlives<'tcx> {
impl<'tcx> TypeRelation<TyCtxt<'tcx>> for MatchAgainstHigherRankedOutlives<'tcx> {
fn tag(&self) -> &'static str {
"MatchAgainstHigherRankedOutlives"
}
@ -145,10 +142,10 @@ fn tcx(&self) -> TyCtxt<'tcx> {
}
#[instrument(level = "trace", skip(self))]
fn relate_with_variance<T: Relate<'tcx>>(
fn relate_with_variance<T: Relate<TyCtxt<'tcx>>>(
&mut self,
variance: ty::Variance,
_: ty::VarianceDiagInfo<'tcx>,
_: ty::VarianceDiagInfo<TyCtxt<'tcx>>,
a: T,
b: T,
) -> RelateResult<'tcx, T> {
@ -208,7 +205,7 @@ fn binders<T>(
value: ty::Binder<'tcx, T>,
) -> RelateResult<'tcx, ty::Binder<'tcx, T>>
where
T: Relate<'tcx>,
T: Relate<TyCtxt<'tcx>>,
{
self.pattern_depth.shift_in(1);
let result = Ok(pattern.rebind(self.relate(pattern.skip_binder(), value.skip_binder())?));

View file

@ -1,11 +1,11 @@
use super::*;
use crate::infer::relate::RelateResult;
use crate::infer::snapshot::CombinedSnapshot;
use rustc_data_structures::fx::FxIndexMap;
use rustc_data_structures::graph::{scc::Sccs, vec_graph::VecGraph};
use rustc_index::Idx;
use rustc_middle::span_bug;
use rustc_middle::ty::error::TypeError;
use rustc_middle::ty::relate::RelateResult;
impl<'tcx> RegionConstraintCollector<'_, 'tcx> {
/// Searches new universes created during `snapshot`, looking for
@ -276,7 +276,7 @@ fn error(
other_region: ty::Region<'tcx>,
) -> TypeError<'tcx> {
debug!("error: placeholder={:?}, other_region={:?}", placeholder, other_region);
TypeError::RegionsInsufficientlyPolymorphic(placeholder.bound.kind, other_region)
TypeError::RegionsInsufficientlyPolymorphic(placeholder.bound, other_region)
}
}

View file

@ -1,8 +1,10 @@
use crate::ty::error::TypeError;
use crate::ty::relate::{self, Relate, RelateResult, TypeRelation};
use crate::ty::{self, InferConst, Ty, TyCtxt};
use rustc_middle::ty::error::{ExpectedFound, TypeError};
use rustc_middle::ty::{self, InferConst, Ty, TyCtxt};
use tracing::{debug, instrument};
use super::{structurally_relate_tys, Relate, RelateResult, TypeRelation};
use crate::infer::relate;
/// A type "A" *matches* "B" if the fresh types in B could be
/// instantiated with values so as to make it equal to A. Matching is
/// intended to be used only on freshened types, and it basically
@ -29,7 +31,7 @@ pub fn new(tcx: TyCtxt<'tcx>) -> MatchAgainstFreshVars<'tcx> {
}
}
impl<'tcx> TypeRelation<'tcx> for MatchAgainstFreshVars<'tcx> {
impl<'tcx> TypeRelation<TyCtxt<'tcx>> for MatchAgainstFreshVars<'tcx> {
fn tag(&self) -> &'static str {
"MatchAgainstFreshVars"
}
@ -38,10 +40,10 @@ fn tcx(&self) -> TyCtxt<'tcx> {
self.tcx
}
fn relate_with_variance<T: Relate<'tcx>>(
fn relate_with_variance<T: Relate<TyCtxt<'tcx>>>(
&mut self,
_: ty::Variance,
_: ty::VarianceDiagInfo<'tcx>,
_: ty::VarianceDiagInfo<TyCtxt<'tcx>>,
a: T,
b: T,
) -> RelateResult<'tcx, T> {
@ -72,12 +74,12 @@ fn tys(&mut self, a: Ty<'tcx>, b: Ty<'tcx>) -> RelateResult<'tcx, Ty<'tcx>> {
) => Ok(a),
(&ty::Infer(_), _) | (_, &ty::Infer(_)) => {
Err(TypeError::Sorts(relate::expected_found(a, b)))
Err(TypeError::Sorts(ExpectedFound::new(true, a, b)))
}
(&ty::Error(guar), _) | (_, &ty::Error(guar)) => Ok(Ty::new_error(self.tcx(), guar)),
_ => relate::structurally_relate_tys(self, a, b),
_ => structurally_relate_tys(self, a, b),
}
}
@ -97,7 +99,7 @@ fn consts(
}
(ty::ConstKind::Infer(_), _) | (_, ty::ConstKind::Infer(_)) => {
return Err(TypeError::ConstMismatch(relate::expected_found(a, b)));
return Err(TypeError::ConstMismatch(ExpectedFound::new(true, a, b)));
}
_ => {}
@ -112,7 +114,7 @@ fn binders<T>(
b: ty::Binder<'tcx, T>,
) -> RelateResult<'tcx, ty::Binder<'tcx, T>>
where
T: Relate<'tcx>,
T: Relate<TyCtxt<'tcx>>,
{
Ok(a.rebind(self.relate(a.skip_binder(), b.skip_binder())?))
}

View file

@ -22,12 +22,13 @@
use super::lub::Lub;
use super::type_relating::TypeRelating;
use super::StructurallyRelateAliases;
use super::{RelateResult, TypeRelation};
use crate::infer::relate;
use crate::infer::{DefineOpaqueTypes, InferCtxt, TypeTrace};
use crate::traits::{Obligation, PredicateObligations};
use rustc_middle::bug;
use rustc_middle::infer::unify_key::EffectVarValue;
use rustc_middle::ty::error::TypeError;
use rustc_middle::ty::relate::{RelateResult, TypeRelation};
use rustc_middle::ty::error::{ExpectedFound, TypeError};
use rustc_middle::ty::{self, InferConst, Ty, TyCtxt, TypeVisitableExt, Upcast};
use rustc_middle::ty::{IntType, UintType};
use rustc_span::Span;
@ -121,7 +122,7 @@ pub fn super_combine_tys<R>(
(_, ty::Alias(..)) | (ty::Alias(..), _) if self.next_trait_solver() => {
match relation.structurally_relate_aliases() {
StructurallyRelateAliases::Yes => {
ty::relate::structurally_relate_tys(relation, a, b)
relate::structurally_relate_tys(relation, a, b)
}
StructurallyRelateAliases::No => {
relation.register_type_relate_obligation(a, b);
@ -132,7 +133,7 @@ pub fn super_combine_tys<R>(
// All other cases of inference are errors
(&ty::Infer(_), _) | (_, &ty::Infer(_)) => {
Err(TypeError::Sorts(ty::relate::expected_found(a, b)))
Err(TypeError::Sorts(ExpectedFound::new(true, a, b)))
}
// During coherence, opaque types should be treated as *possibly*
@ -144,7 +145,7 @@ pub fn super_combine_tys<R>(
Ok(a)
}
_ => ty::relate::structurally_relate_tys(relation, a, b),
_ => relate::structurally_relate_tys(relation, a, b),
}
}
@ -234,11 +235,11 @@ pub fn super_combine_consts<R>(
Ok(b)
}
StructurallyRelateAliases::Yes => {
ty::relate::structurally_relate_consts(relation, a, b)
relate::structurally_relate_consts(relation, a, b)
}
}
}
_ => ty::relate::structurally_relate_consts(relation, a, b),
_ => relate::structurally_relate_consts(relation, a, b),
}
}
@ -303,7 +304,7 @@ pub fn register_predicates(
}
}
pub trait ObligationEmittingRelation<'tcx>: TypeRelation<'tcx> {
pub trait ObligationEmittingRelation<'tcx>: TypeRelation<TyCtxt<'tcx>> {
fn span(&self) -> Span;
fn param_env(&self) -> ty::ParamEnv<'tcx>;

View file

@ -1,15 +1,16 @@
use std::mem;
use super::StructurallyRelateAliases;
use super::{ObligationEmittingRelation, Relate, RelateResult, TypeRelation};
use crate::infer::relate;
use crate::infer::type_variable::TypeVariableValue;
use crate::infer::{InferCtxt, ObligationEmittingRelation, RegionVariableOrigin};
use crate::infer::{InferCtxt, RegionVariableOrigin};
use rustc_data_structures::sso::SsoHashMap;
use rustc_data_structures::stack::ensure_sufficient_stack;
use rustc_hir::def_id::DefId;
use rustc_middle::bug;
use rustc_middle::infer::unify_key::ConstVariableValue;
use rustc_middle::ty::error::TypeError;
use rustc_middle::ty::relate::{self, Relate, RelateResult, TypeRelation};
use rustc_middle::ty::visit::MaxUniverse;
use rustc_middle::ty::{self, Ty, TyCtxt};
use rustc_middle::ty::{AliasRelationDirection, InferConst, Term, TypeVisitable, TypeVisitableExt};
@ -228,7 +229,7 @@ pub(super) fn instantiate_const_var<R: ObligationEmittingRelation<'tcx>>(
/// Attempts to generalize `source_term` for the type variable `target_vid`.
/// This checks for cycles -- that is, whether `source_term` references `target_vid`.
fn generalize<T: Into<Term<'tcx>> + Relate<'tcx>>(
fn generalize<T: Into<Term<'tcx>> + Relate<TyCtxt<'tcx>>>(
&self,
span: Span,
structurally_relate_aliases: StructurallyRelateAliases,
@ -395,7 +396,7 @@ fn generalize_alias_ty(
}
}
impl<'tcx> TypeRelation<'tcx> for Generalizer<'_, 'tcx> {
impl<'tcx> TypeRelation<TyCtxt<'tcx>> for Generalizer<'_, 'tcx> {
fn tcx(&self) -> TyCtxt<'tcx> {
self.infcx.tcx
}
@ -430,10 +431,10 @@ fn relate_item_args(
}
#[instrument(level = "debug", skip(self, variance, b), ret)]
fn relate_with_variance<T: Relate<'tcx>>(
fn relate_with_variance<T: Relate<TyCtxt<'tcx>>>(
&mut self,
variance: ty::Variance,
_info: ty::VarianceDiagInfo<'tcx>,
_info: ty::VarianceDiagInfo<TyCtxt<'tcx>>,
a: T,
b: T,
) -> RelateResult<'tcx, T> {
@ -695,7 +696,7 @@ fn binders<T>(
_: ty::Binder<'tcx, T>,
) -> RelateResult<'tcx, ty::Binder<'tcx, T>>
where
T: Relate<'tcx>,
T: Relate<TyCtxt<'tcx>>,
{
let result = self.relate(a.skip_binder(), a.skip_binder())?;
Ok(a.rebind(result))

View file

@ -1,6 +1,6 @@
//! Greatest lower bound. See [`lattice`].
use rustc_middle::ty::relate::{Relate, RelateResult, TypeRelation};
use super::{Relate, RelateResult, TypeRelation};
use rustc_middle::ty::{self, Ty, TyCtxt, TypeVisitableExt};
use rustc_span::Span;
@ -21,7 +21,7 @@ pub fn new(fields: &'combine mut CombineFields<'infcx, 'tcx>) -> Glb<'combine, '
}
}
impl<'tcx> TypeRelation<'tcx> for Glb<'_, '_, 'tcx> {
impl<'tcx> TypeRelation<TyCtxt<'tcx>> for Glb<'_, '_, 'tcx> {
fn tag(&self) -> &'static str {
"Glb"
}
@ -30,10 +30,10 @@ fn tcx(&self) -> TyCtxt<'tcx> {
self.fields.tcx()
}
fn relate_with_variance<T: Relate<'tcx>>(
fn relate_with_variance<T: Relate<TyCtxt<'tcx>>>(
&mut self,
variance: ty::Variance,
_info: ty::VarianceDiagInfo<'tcx>,
_info: ty::VarianceDiagInfo<TyCtxt<'tcx>>,
a: T,
b: T,
) -> RelateResult<'tcx, T> {
@ -81,7 +81,7 @@ fn binders<T>(
b: ty::Binder<'tcx, T>,
) -> RelateResult<'tcx, ty::Binder<'tcx, T>>
where
T: Relate<'tcx>,
T: Relate<TyCtxt<'tcx>>,
{
// GLB of a binder and itself is just itself
if a == b {

View file

@ -1,10 +1,10 @@
//! Helper routines for higher-ranked things. See the `doc` module at
//! the end of the file for details.
use super::RelateResult;
use crate::infer::snapshot::CombinedSnapshot;
use crate::infer::InferCtxt;
use rustc_middle::ty::fold::FnMutDelegate;
use rustc_middle::ty::relate::RelateResult;
use rustc_middle::ty::{self, Ty, TyCtxt, TypeFoldable};
impl<'tcx> InferCtxt<'tcx> {

View file

@ -21,7 +21,7 @@
use crate::infer::{DefineOpaqueTypes, InferCtxt};
use crate::traits::ObligationCause;
use rustc_middle::ty::relate::RelateResult;
use super::RelateResult;
use rustc_middle::ty::TyVar;
use rustc_middle::ty::{self, Ty};

View file

@ -6,7 +6,7 @@
use crate::infer::{DefineOpaqueTypes, InferCtxt, SubregionOrigin};
use crate::traits::{ObligationCause, PredicateObligations};
use rustc_middle::ty::relate::{Relate, RelateResult, TypeRelation};
use super::{Relate, RelateResult, TypeRelation};
use rustc_middle::ty::{self, Ty, TyCtxt, TypeVisitableExt};
use rustc_span::Span;
@ -21,7 +21,7 @@ pub fn new(fields: &'combine mut CombineFields<'infcx, 'tcx>) -> Lub<'combine, '
}
}
impl<'tcx> TypeRelation<'tcx> for Lub<'_, '_, 'tcx> {
impl<'tcx> TypeRelation<TyCtxt<'tcx>> for Lub<'_, '_, 'tcx> {
fn tag(&self) -> &'static str {
"Lub"
}
@ -30,10 +30,10 @@ fn tcx(&self) -> TyCtxt<'tcx> {
self.fields.tcx()
}
fn relate_with_variance<T: Relate<'tcx>>(
fn relate_with_variance<T: Relate<TyCtxt<'tcx>>>(
&mut self,
variance: ty::Variance,
_info: ty::VarianceDiagInfo<'tcx>,
_info: ty::VarianceDiagInfo<TyCtxt<'tcx>>,
a: T,
b: T,
) -> RelateResult<'tcx, T> {
@ -81,7 +81,7 @@ fn binders<T>(
b: ty::Binder<'tcx, T>,
) -> RelateResult<'tcx, ty::Binder<'tcx, T>>
where
T: Relate<'tcx>,
T: Relate<TyCtxt<'tcx>>,
{
// LUB of a binder and itself is just itself
if a == b {

View file

@ -1,6 +1,14 @@
//! This module contains the definitions of most `TypeRelation`s in the type system
//! (except for some relations used for diagnostics and heuristics in the compiler).
//! As well as the implementation of `Relate` for interned things (`Ty`/`Const`/etc).
pub use rustc_middle::ty::relate::*;
pub use self::_match::MatchAgainstFreshVars;
pub use self::combine::CombineFields;
pub use self::combine::ObligationEmittingRelation;
pub mod _match;
pub(super) mod combine;
mod generalize;
mod glb;
@ -8,15 +16,3 @@
mod lattice;
mod lub;
mod type_relating;
/// Whether aliases should be related structurally or not. Used
/// to adjust the behavior of generalization and combine.
///
/// This should always be `No` unless in a few special-cases when
/// instantiating canonical responses and in the new solver. Each
/// such case should have a comment explaining why it is used.
#[derive(Debug, Copy, Clone)]
pub enum StructurallyRelateAliases {
Yes,
No,
}

View file

@ -1,12 +1,11 @@
use super::combine::CombineFields;
use crate::infer::BoundRegionConversionTime::HigherRankedType;
use crate::infer::{
DefineOpaqueTypes, ObligationEmittingRelation, StructurallyRelateAliases, SubregionOrigin,
};
use crate::infer::{DefineOpaqueTypes, SubregionOrigin};
use crate::traits::{Obligation, PredicateObligations};
use rustc_middle::ty::relate::{
relate_args_invariantly, relate_args_with_variances, Relate, RelateResult, TypeRelation,
use super::{
relate_args_invariantly, relate_args_with_variances, ObligationEmittingRelation, Relate,
RelateResult, StructurallyRelateAliases, TypeRelation,
};
use rustc_middle::ty::TyVar;
use rustc_middle::ty::{self, Ty, TyCtxt};
@ -29,7 +28,7 @@ pub fn new(
}
}
impl<'tcx> TypeRelation<'tcx> for TypeRelating<'_, '_, 'tcx> {
impl<'tcx> TypeRelation<TyCtxt<'tcx>> for TypeRelating<'_, '_, 'tcx> {
fn tag(&self) -> &'static str {
"TypeRelating"
}
@ -56,10 +55,10 @@ fn relate_item_args(
}
}
fn relate_with_variance<T: Relate<'tcx>>(
fn relate_with_variance<T: Relate<TyCtxt<'tcx>>>(
&mut self,
variance: ty::Variance,
_info: ty::VarianceDiagInfo<'tcx>,
_info: ty::VarianceDiagInfo<TyCtxt<'tcx>>,
a: T,
b: T,
) -> RelateResult<'tcx, T> {
@ -226,7 +225,7 @@ fn binders<T>(
b: ty::Binder<'tcx, T>,
) -> RelateResult<'tcx, ty::Binder<'tcx, T>>
where
T: Relate<'tcx>,
T: Relate<TyCtxt<'tcx>>,
{
if a == b {
// Do nothing

View file

@ -51,7 +51,7 @@
use rustc_hir::def::{DefKind, Res};
use rustc_hir::def_id::{DefId, LocalDefId, CRATE_DEF_ID};
use rustc_hir::intravisit::FnKind as HirFnKind;
use rustc_hir::{Body, FnDecl, GenericParamKind, Node, PatKind, PredicateOrigin};
use rustc_hir::{Body, FnDecl, GenericParamKind, PatKind, PredicateOrigin};
use rustc_middle::bug;
use rustc_middle::lint::in_external_macro;
use rustc_middle::ty::layout::LayoutOf;
@ -1423,11 +1423,20 @@ fn check_foreign_item(&mut self, cx: &LateContext<'_>, foreign_item: &hir::Forei
self.perform_lint(cx, "item", foreign_item.owner_id.def_id, foreign_item.vis_span, true);
}
fn check_field_def(&mut self, cx: &LateContext<'_>, field: &hir::FieldDef<'_>) {
if matches!(cx.tcx.parent_hir_node(field.hir_id), Node::Variant(_)) {
return;
}
self.perform_lint(cx, "field", field.def_id, field.vis_span, false);
fn check_field_def(&mut self, _cx: &LateContext<'_>, _field: &hir::FieldDef<'_>) {
// - If an ADT definition is reported then we don't need to check fields
// (as it would add unnecessary complexity to the source code, the struct
// definition is in the immediate proximity to give the "real" visibility).
// - If an ADT is not reported because it's not `pub` - we don't need to
// check fields.
// - If an ADT is not reported because it's reachable - we also don't need
// to check fields because then they are reachable by construction if they
// are pub.
//
// Therefore in no case we check the fields.
//
// cf. https://github.com/rust-lang/rust/pull/126013#issuecomment-2152839205
// cf. https://github.com/rust-lang/rust/pull/126040#issuecomment-2152944506
}
fn check_impl_item(&mut self, cx: &LateContext<'_>, impl_item: &hir::ImplItem<'_>) {

View file

@ -581,7 +581,6 @@ fn maybe_resolve_crate<'b>(
self.tcx.crate_types().iter().all(|c| *c == CrateType::Rlib),
hash,
extra_filename,
false, // is_host
path_kind,
);

View file

@ -222,7 +222,6 @@
use rustc_data_structures::svh::Svh;
use rustc_errors::{DiagArgValue, IntoDiagArg};
use rustc_fs_util::try_canonicalize;
use rustc_session::config;
use rustc_session::cstore::CrateSource;
use rustc_session::filesearch::FileSearch;
use rustc_session::search_paths::PathKind;
@ -309,7 +308,6 @@ pub(crate) fn new(
is_rlib: bool,
hash: Option<Svh>,
extra_filename: Option<&'a str>,
is_host: bool,
path_kind: PathKind,
) -> CrateLocator<'a> {
let needs_object_code = sess.opts.output_types.should_codegen();
@ -340,17 +338,9 @@ pub(crate) fn new(
},
hash,
extra_filename,
target: if is_host { &sess.host } else { &sess.target },
triple: if is_host {
TargetTriple::from_triple(config::host_triple())
} else {
sess.opts.target_triple.clone()
},
filesearch: if is_host {
sess.host_filesearch(path_kind)
} else {
sess.target_filesearch(path_kind)
},
target: &sess.target,
triple: sess.opts.target_triple.clone(),
filesearch: sess.target_filesearch(path_kind),
is_proc_macro: false,
crate_rejections: CrateRejections::default(),
}
@ -424,12 +414,18 @@ fn find_library_crate(
debug!("testing {}", spf.path.display());
let f = &spf.file_name_str;
let (hash, kind) = if f.starts_with(rlib_prefix) && f.ends_with(rlib_suffix) {
(&f[rlib_prefix.len()..(f.len() - rlib_suffix.len())], CrateFlavor::Rlib)
} else if f.starts_with(rmeta_prefix) && f.ends_with(rmeta_suffix) {
(&f[rmeta_prefix.len()..(f.len() - rmeta_suffix.len())], CrateFlavor::Rmeta)
} else if f.starts_with(dylib_prefix) && f.ends_with(dylib_suffix.as_ref()) {
(&f[dylib_prefix.len()..(f.len() - dylib_suffix.len())], CrateFlavor::Dylib)
let (hash, kind) = if let Some(f) = f.strip_prefix(rlib_prefix)
&& let Some(f) = f.strip_suffix(rlib_suffix)
{
(f, CrateFlavor::Rlib)
} else if let Some(f) = f.strip_prefix(rmeta_prefix)
&& let Some(f) = f.strip_suffix(rmeta_suffix)
{
(f, CrateFlavor::Rmeta)
} else if let Some(f) = f.strip_prefix(dylib_prefix)
&& let Some(f) = f.strip_suffix(dylib_suffix.as_ref())
{
(f, CrateFlavor::Dylib)
} else {
if f.starts_with(staticlib_prefix) && f.ends_with(staticlib_suffix.as_ref()) {
self.crate_rejections.via_kind.push(CrateMismatch {

View file

@ -28,7 +28,6 @@ rustc_hir = { path = "../rustc_hir" }
rustc_hir_pretty = { path = "../rustc_hir_pretty" }
rustc_index = { path = "../rustc_index" }
rustc_macros = { path = "../rustc_macros" }
rustc_next_trait_solver = { path = "../rustc_next_trait_solver" }
rustc_query_system = { path = "../rustc_query_system" }
rustc_serialize = { path = "../rustc_serialize" }
rustc_session = { path = "../rustc_session" }

View file

@ -62,7 +62,7 @@ macro_rules! arena_types {
[] candidate_step: rustc_middle::traits::query::CandidateStep<'tcx>,
[] autoderef_bad_ty: rustc_middle::traits::query::MethodAutoderefBadTy<'tcx>,
[] canonical_goal_evaluation:
rustc_next_trait_solver::solve::inspect::CanonicalGoalEvaluationStep<
rustc_type_ir::solve::inspect::CanonicalGoalEvaluationStep<
rustc_middle::ty::TyCtxt<'tcx>
>,
[] query_region_constraints: rustc_middle::infer::canonical::QueryRegionConstraints<'tcx>,

View file

@ -32,7 +32,7 @@
pub use self::select::{EvaluationCache, EvaluationResult, OverflowError, SelectionCache};
// FIXME: Remove this import and import via `solve::`
pub use rustc_next_trait_solver::solve::BuiltinImplSource;
pub use rustc_type_ir::solve::BuiltinImplSource;
/// Depending on the stage of compilation, we want projection to be
/// more or less conservative.

View file

@ -7,13 +7,12 @@
use crate::error::DropCheckOverflow;
use crate::infer::canonical::{Canonical, QueryResponse};
use crate::ty::error::TypeError;
use crate::ty::GenericArg;
use crate::ty::{self, Ty, TyCtxt};
use rustc_macros::{HashStable, TypeFoldable, TypeVisitable};
use rustc_span::Span;
// FIXME: Remove this import and import via `traits::solve`.
pub use rustc_next_trait_solver::solve::NoSolution;
pub use rustc_type_ir::solve::NoSolution;
pub mod type_op {
use crate::ty::fold::TypeFoldable;
@ -91,12 +90,6 @@ pub fn new(value: T) -> Self {
pub type CanonicalTypeOpNormalizeGoal<'tcx, T> =
Canonical<'tcx, ty::ParamEnvAnd<'tcx, type_op::Normalize<T>>>;
impl<'tcx> From<TypeError<'tcx>> for NoSolution {
fn from(_: TypeError<'tcx>) -> NoSolution {
NoSolution
}
}
#[derive(Clone, Debug, Default, HashStable, TypeFoldable, TypeVisitable)]
pub struct DropckOutlivesResult<'tcx> {
pub kinds: Vec<GenericArg<'tcx>>,

View file

@ -1,8 +1,8 @@
use rustc_ast_ir::try_visit;
use rustc_data_structures::intern::Interned;
use rustc_macros::{HashStable, TypeFoldable, TypeVisitable};
use rustc_next_trait_solver as ir;
pub use rustc_next_trait_solver::solve::*;
use rustc_type_ir as ir;
pub use rustc_type_ir::solve::*;
use crate::infer::canonical::QueryRegionConstraints;
use crate::ty::{

View file

@ -200,6 +200,12 @@ pub fn repr(self) -> ReprOptions {
}
}
impl<'tcx> rustc_type_ir::inherent::AdtDef<TyCtxt<'tcx>> for AdtDef<'tcx> {
fn def_id(self) -> DefId {
self.did()
}
}
#[derive(Copy, Clone, Debug, Eq, PartialEq, HashStable, TyEncodable, TyDecodable)]
pub enum AdtKind {
Struct,

View file

@ -149,6 +149,10 @@ pub fn new_error_with_message<S: Into<MultiSpan>>(
}
impl<'tcx> rustc_type_ir::inherent::Const<TyCtxt<'tcx>> for Const<'tcx> {
fn try_to_target_usize(self, interner: TyCtxt<'tcx>) -> Option<u64> {
self.try_to_target_usize(interner)
}
fn new_infer(tcx: TyCtxt<'tcx>, infer: ty::InferConst) -> Self {
Const::new_infer(tcx, infer)
}
@ -168,6 +172,10 @@ fn new_anon_bound(tcx: TyCtxt<'tcx>, debruijn: ty::DebruijnIndex, var: ty::Bound
fn new_unevaluated(interner: TyCtxt<'tcx>, uv: ty::UnevaluatedConst<'tcx>) -> Self {
Const::new_unevaluated(interner, uv)
}
fn new_expr(interner: TyCtxt<'tcx>, expr: ty::Expr<'tcx>) -> Self {
Const::new_expr(interner, expr)
}
}
impl<'tcx> Const<'tcx> {

View file

@ -69,6 +69,7 @@
use rustc_span::{Span, DUMMY_SP};
use rustc_target::abi::{FieldIdx, Layout, LayoutS, TargetDataLayout, VariantIdx};
use rustc_target::spec::abi;
use rustc_type_ir::fold::TypeFoldable;
use rustc_type_ir::TyKind::*;
use rustc_type_ir::WithCachedTypeInfo;
use rustc_type_ir::{CollectAndApply, Interner, TypeFlags};
@ -135,9 +136,12 @@ impl<'tcx> Interner for TyCtxt<'tcx> {
type ParamEnv = ty::ParamEnv<'tcx>;
type Predicate = Predicate<'tcx>;
type Clause = Clause<'tcx>;
type Clauses = ty::Clauses<'tcx>;
fn expand_abstract_consts<T: TypeFoldable<TyCtxt<'tcx>>>(self, t: T) -> T {
self.expand_abstract_consts(t)
}
fn mk_canonical_var_infos(self, infos: &[ty::CanonicalVarInfo<Self>]) -> Self::CanonicalVars {
self.mk_canonical_var_infos(infos)
}
@ -148,6 +152,12 @@ fn generics_of(self, def_id: DefId) -> &'tcx ty::Generics {
self.generics_of(def_id)
}
type VariancesOf = &'tcx [ty::Variance];
fn variances_of(self, def_id: Self::DefId) -> Self::VariancesOf {
self.variances_of(def_id)
}
fn type_of(self, def_id: DefId) -> ty::EarlyBinder<'tcx, Ty<'tcx>> {
self.type_of(def_id)
}
@ -205,7 +215,11 @@ fn mk_args(self, args: &[Self::GenericArg]) -> Self::GenericArgs {
self.mk_args(args)
}
fn mk_args_from_iter(self, args: impl Iterator<Item = Self::GenericArg>) -> Self::GenericArgs {
fn mk_args_from_iter<I, T>(self, args: I) -> T::Output
where
I: Iterator<Item = T>,
T: CollectAndApply<Self::GenericArg, Self::GenericArgs>,
{
self.mk_args_from_iter(args)
}
@ -224,6 +238,14 @@ fn intern_canonical_goal_evaluation_step(
self.arena.alloc(step)
}
fn mk_type_list_from_iter<I, T>(self, args: I) -> T::Output
where
I: Iterator<Item = T>,
T: CollectAndApply<Self::Ty, Self::Tys>,
{
self.mk_type_list_from_iter(args)
}
fn parent(self, def_id: Self::DefId) -> Self::DefId {
self.parent(def_id)
}
@ -231,6 +253,12 @@ fn parent(self, def_id: Self::DefId) -> Self::DefId {
fn recursion_limit(self) -> usize {
self.recursion_limit().0
}
type Features = &'tcx rustc_feature::Features;
fn features(self) -> Self::Features {
self.features()
}
}
impl<'tcx> rustc_type_ir::inherent::Abi<TyCtxt<'tcx>> for abi::Abi {
@ -249,6 +277,12 @@ fn prefix_str(self) -> &'static str {
}
}
impl<'tcx> rustc_type_ir::inherent::Features<TyCtxt<'tcx>> for &'tcx rustc_feature::Features {
fn generic_const_exprs(self) -> bool {
self.generic_const_exprs
}
}
type InternedSet<'tcx, T> = ShardedHashMap<InternedInSet<'tcx, T>, ()>;
pub struct CtxtInterners<'tcx> {

View file

@ -1,89 +1,26 @@
use crate::ty::print::{with_forced_trimmed_paths, FmtPrinter, PrettyPrinter};
use crate::ty::{self, BoundRegionKind, Region, Ty, TyCtxt};
use crate::ty::{self, Ty, TyCtxt};
use rustc_errors::pluralize;
use rustc_hir as hir;
use rustc_hir::def::{CtorOf, DefKind};
use rustc_hir::def_id::DefId;
use rustc_macros::{TypeFoldable, TypeVisitable};
use rustc_span::symbol::Symbol;
use rustc_target::spec::abi;
use rustc_macros::extension;
pub use rustc_type_ir::error::ExpectedFound;
use std::borrow::Cow;
use std::hash::{DefaultHasher, Hash, Hasher};
use std::path::PathBuf;
#[derive(Clone, Copy, Debug, PartialEq, Eq, TypeFoldable, TypeVisitable)]
pub struct ExpectedFound<T> {
pub expected: T,
pub found: T,
}
pub type TypeError<'tcx> = rustc_type_ir::error::TypeError<TyCtxt<'tcx>>;
impl<T> ExpectedFound<T> {
pub fn new(a_is_expected: bool, a: T, b: T) -> Self {
if a_is_expected {
ExpectedFound { expected: a, found: b }
} else {
ExpectedFound { expected: b, found: a }
}
}
}
// Data structures used in type unification
#[derive(Copy, Clone, Debug, TypeVisitable, PartialEq, Eq)]
#[rustc_pass_by_value]
pub enum TypeError<'tcx> {
Mismatch,
ConstnessMismatch(ExpectedFound<ty::BoundConstness>),
PolarityMismatch(ExpectedFound<ty::PredicatePolarity>),
SafetyMismatch(ExpectedFound<hir::Safety>),
AbiMismatch(ExpectedFound<abi::Abi>),
Mutability,
ArgumentMutability(usize),
TupleSize(ExpectedFound<usize>),
FixedArraySize(ExpectedFound<u64>),
ArgCount,
FieldMisMatch(Symbol, Symbol),
RegionsDoesNotOutlive(Region<'tcx>, Region<'tcx>),
RegionsInsufficientlyPolymorphic(BoundRegionKind, Region<'tcx>),
RegionsPlaceholderMismatch,
Sorts(ExpectedFound<Ty<'tcx>>),
ArgumentSorts(ExpectedFound<Ty<'tcx>>, usize),
Traits(ExpectedFound<DefId>),
VariadicMismatch(ExpectedFound<bool>),
/// Instantiating a type variable with the given type would have
/// created a cycle (because it appears somewhere within that
/// type).
CyclicTy(Ty<'tcx>),
CyclicConst(ty::Const<'tcx>),
ProjectionMismatched(ExpectedFound<DefId>),
ExistentialMismatch(ExpectedFound<&'tcx ty::List<ty::PolyExistentialPredicate<'tcx>>>),
ConstMismatch(ExpectedFound<ty::Const<'tcx>>),
IntrinsicCast,
/// Safe `#[target_feature]` functions are not assignable to safe function pointers.
TargetFeatureCast(DefId),
}
impl TypeError<'_> {
pub fn involves_regions(self) -> bool {
match self {
TypeError::RegionsDoesNotOutlive(_, _)
| TypeError::RegionsInsufficientlyPolymorphic(_, _)
| TypeError::RegionsPlaceholderMismatch => true,
_ => false,
}
}
}
/// Explains the source of a type err in a short, human readable way. This is meant to be placed
/// in parentheses after some larger message. You should also invoke `note_and_explain_type_err()`
/// afterwards to present additional details, particularly when it comes to lifetime-related
/// errors.
/// Explains the source of a type err in a short, human readable way.
/// This is meant to be placed in parentheses after some larger message.
/// You should also invoke `note_and_explain_type_err()` afterwards
/// to present additional details, particularly when it comes to lifetime-
/// related errors.
#[extension(pub trait TypeErrorToStringExt<'tcx>)]
impl<'tcx> TypeError<'tcx> {
pub fn to_string(self, tcx: TyCtxt<'tcx>) -> Cow<'static, str> {
use self::TypeError::*;
fn to_string(self, tcx: TyCtxt<'tcx>) -> Cow<'static, str> {
fn report_maybe_different(expected: &str, found: &str) -> String {
// A naive approach to making sure that we're not reporting silly errors such as:
// (expected closure, found closure).
@ -95,24 +32,26 @@ fn report_maybe_different(expected: &str, found: &str) -> String {
}
match self {
CyclicTy(_) => "cyclic type of infinite size".into(),
CyclicConst(_) => "encountered a self-referencing constant".into(),
Mismatch => "types differ".into(),
ConstnessMismatch(values) => {
TypeError::CyclicTy(_) => "cyclic type of infinite size".into(),
TypeError::CyclicConst(_) => "encountered a self-referencing constant".into(),
TypeError::Mismatch => "types differ".into(),
TypeError::ConstnessMismatch(values) => {
format!("expected {} bound, found {} bound", values.expected, values.found).into()
}
PolarityMismatch(values) => {
TypeError::PolarityMismatch(values) => {
format!("expected {} polarity, found {} polarity", values.expected, values.found)
.into()
}
SafetyMismatch(values) => {
TypeError::SafetyMismatch(values) => {
format!("expected {} fn, found {} fn", values.expected, values.found).into()
}
AbiMismatch(values) => {
TypeError::AbiMismatch(values) => {
format!("expected {} fn, found {} fn", values.expected, values.found).into()
}
ArgumentMutability(_) | Mutability => "types differ in mutability".into(),
TupleSize(values) => format!(
TypeError::ArgumentMutability(_) | TypeError::Mutability => {
"types differ in mutability".into()
}
TypeError::TupleSize(values) => format!(
"expected a tuple with {} element{}, found one with {} element{}",
values.expected,
pluralize!(values.expected),
@ -120,7 +59,7 @@ fn report_maybe_different(expected: &str, found: &str) -> String {
pluralize!(values.found)
)
.into(),
FixedArraySize(values) => format!(
TypeError::FixedArraySize(values) => format!(
"expected an array with a fixed size of {} element{}, found one with {} element{}",
values.expected,
pluralize!(values.expected),
@ -128,20 +67,21 @@ fn report_maybe_different(expected: &str, found: &str) -> String {
pluralize!(values.found)
)
.into(),
ArgCount => "incorrect number of function parameters".into(),
FieldMisMatch(adt, field) => format!("field type mismatch: {adt}.{field}").into(),
RegionsDoesNotOutlive(..) => "lifetime mismatch".into(),
TypeError::ArgCount => "incorrect number of function parameters".into(),
TypeError::RegionsDoesNotOutlive(..) => "lifetime mismatch".into(),
// Actually naming the region here is a bit confusing because context is lacking
RegionsInsufficientlyPolymorphic(..) => {
TypeError::RegionsInsufficientlyPolymorphic(..) => {
"one type is more general than the other".into()
}
RegionsPlaceholderMismatch => "one type is more general than the other".into(),
ArgumentSorts(values, _) | Sorts(values) => {
TypeError::RegionsPlaceholderMismatch => {
"one type is more general than the other".into()
}
TypeError::ArgumentSorts(values, _) | TypeError::Sorts(values) => {
let expected = values.expected.sort_string(tcx);
let found = values.found.sort_string(tcx);
report_maybe_different(&expected, &found).into()
}
Traits(values) => {
TypeError::Traits(values) => {
let (mut expected, mut found) = with_forced_trimmed_paths!((
tcx.def_path_str(values.expected),
tcx.def_path_str(values.found),
@ -153,59 +93,34 @@ fn report_maybe_different(expected: &str, found: &str) -> String {
report_maybe_different(&format!("trait `{expected}`"), &format!("trait `{found}`"))
.into()
}
VariadicMismatch(ref values) => format!(
TypeError::VariadicMismatch(ref values) => format!(
"expected {} fn, found {} function",
if values.expected { "variadic" } else { "non-variadic" },
if values.found { "variadic" } else { "non-variadic" }
)
.into(),
ProjectionMismatched(ref values) => format!(
TypeError::ProjectionMismatched(ref values) => format!(
"expected `{}`, found `{}`",
tcx.def_path_str(values.expected),
tcx.def_path_str(values.found)
)
.into(),
ExistentialMismatch(ref values) => report_maybe_different(
TypeError::ExistentialMismatch(ref values) => report_maybe_different(
&format!("trait `{}`", values.expected),
&format!("trait `{}`", values.found),
)
.into(),
ConstMismatch(ref values) => {
TypeError::ConstMismatch(ref values) => {
format!("expected `{}`, found `{}`", values.expected, values.found).into()
}
IntrinsicCast => "cannot coerce intrinsics to function pointers".into(),
TargetFeatureCast(_) => {
TypeError::IntrinsicCast => "cannot coerce intrinsics to function pointers".into(),
TypeError::TargetFeatureCast(_) => {
"cannot coerce functions with `#[target_feature]` to safe function pointers".into()
}
}
}
}
impl<'tcx> TypeError<'tcx> {
pub fn must_include_note(self) -> bool {
use self::TypeError::*;
match self {
CyclicTy(_) | CyclicConst(_) | SafetyMismatch(_) | ConstnessMismatch(_)
| PolarityMismatch(_) | Mismatch | AbiMismatch(_) | FixedArraySize(_)
| ArgumentSorts(..) | Sorts(_) | VariadicMismatch(_) | TargetFeatureCast(_) => false,
Mutability
| ArgumentMutability(_)
| TupleSize(_)
| ArgCount
| FieldMisMatch(..)
| RegionsDoesNotOutlive(..)
| RegionsInsufficientlyPolymorphic(..)
| RegionsPlaceholderMismatch
| Traits(_)
| ProjectionMismatched(_)
| ExistentialMismatch(_)
| ConstMismatch(_)
| IntrinsicCast => true,
}
}
}
impl<'tcx> Ty<'tcx> {
pub fn sort_string(self, tcx: TyCtxt<'tcx>) -> Cow<'static, str> {
match *self.kind() {

View file

@ -60,6 +60,7 @@
use rustc_span::{ExpnId, ExpnKind, Span};
use rustc_target::abi::{Align, FieldIdx, Integer, IntegerType, VariantIdx};
pub use rustc_target::abi::{ReprFlags, ReprOptions};
pub use rustc_type_ir::relate::VarianceDiagInfo;
pub use rustc_type_ir::{DebugWithInfcx, InferCtxtLike, WithInfcx};
use tracing::{debug, instrument};
pub use vtable::*;
@ -114,7 +115,7 @@
pub use self::sty::{
AliasTy, Article, Binder, BoundTy, BoundTyKind, BoundVariableKind, CanonicalPolyFnSig,
CoroutineArgsExt, EarlyBinder, FnSig, InlineConstArgs, InlineConstArgsParts, ParamConst,
ParamTy, PolyFnSig, TyKind, TypeAndMut, UpvarArgs, VarianceDiagInfo,
ParamTy, PolyFnSig, TyKind, TypeAndMut, UpvarArgs,
};
pub use self::trait_def::TraitDef;
pub use self::typeck_results::{
@ -122,7 +123,6 @@
TypeckResults, UserType, UserTypeAnnotationIndex,
};
pub mod _match;
pub mod abstract_const;
pub mod adjustment;
pub mod cast;
@ -313,38 +313,6 @@ pub fn to_string(self, def_id: LocalDefId, tcx: TyCtxt<'_>) -> String {
}
}
#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, HashStable, TyEncodable, TyDecodable)]
pub enum BoundConstness {
/// `Type: Trait`
NotConst,
/// `Type: const Trait`
Const,
/// `Type: ~const Trait`
///
/// Requires resolving to const only when we are in a const context.
ConstIfConst,
}
impl BoundConstness {
pub fn as_str(self) -> &'static str {
match self {
Self::NotConst => "",
Self::Const => "const",
Self::ConstIfConst => "~const",
}
}
}
impl fmt::Display for BoundConstness {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
Self::NotConst => f.write_str("normal"),
Self::Const => f.write_str("const"),
Self::ConstIfConst => f.write_str("~const"),
}
}
}
#[derive(Clone, Debug, PartialEq, Eq, Copy, Hash, TyEncodable, TyDecodable, HashStable)]
#[derive(TypeFoldable, TypeVisitable)]
pub struct ClosureSizeProfileData<'tcx> {

View file

@ -1,383 +1,54 @@
//! Generalized type relating mechanism.
//!
//! A type relation `R` relates a pair of values `(A, B)`. `A and B` are usually
//! types or regions but can be other things. Examples of type relations are
//! subtyping, type equality, etc.
use std::iter;
use rustc_hir as hir;
use rustc_target::spec::abi;
pub use rustc_type_ir::relate::*;
use crate::ty::error::{ExpectedFound, TypeError};
use crate::ty::{
self, ExistentialPredicate, ExistentialPredicateStableCmpExt as _, GenericArg, GenericArgKind,
GenericArgsRef, ImplSubject, Term, TermKind, Ty, TyCtxt, TypeFoldable,
};
use rustc_hir as hir;
use rustc_hir::def_id::DefId;
use rustc_macros::TypeVisitable;
use rustc_target::spec::abi;
use std::iter;
use tracing::{debug, instrument};
use crate::ty::predicate::ExistentialPredicateStableCmpExt as _;
use crate::ty::{self as ty, Ty, TyCtxt};
use super::Pattern;
pub type RelateResult<'tcx, T> = rustc_type_ir::relate::RelateResult<TyCtxt<'tcx>, T>;
pub type RelateResult<'tcx, T> = Result<T, TypeError<'tcx>>;
pub trait TypeRelation<'tcx>: Sized {
fn tcx(&self) -> TyCtxt<'tcx>;
/// Returns a static string we can use for printouts.
fn tag(&self) -> &'static str;
/// Generic relation routine suitable for most anything.
fn relate<T: Relate<'tcx>>(&mut self, a: T, b: T) -> RelateResult<'tcx, T> {
Relate::relate(self, a, b)
}
/// Relate the two args for the given item. The default
/// is to look up the variance for the item and proceed
/// accordingly.
fn relate_item_args(
&mut self,
item_def_id: DefId,
a_arg: GenericArgsRef<'tcx>,
b_arg: GenericArgsRef<'tcx>,
) -> RelateResult<'tcx, GenericArgsRef<'tcx>> {
debug!(
"relate_item_args(item_def_id={:?}, a_arg={:?}, b_arg={:?})",
item_def_id, a_arg, b_arg
);
let tcx = self.tcx();
let opt_variances = tcx.variances_of(item_def_id);
relate_args_with_variances(self, item_def_id, opt_variances, a_arg, b_arg, true)
}
/// Switch variance for the purpose of relating `a` and `b`.
fn relate_with_variance<T: Relate<'tcx>>(
&mut self,
variance: ty::Variance,
info: ty::VarianceDiagInfo<'tcx>,
a: T,
b: T,
) -> RelateResult<'tcx, T>;
// Overridable relations. You shouldn't typically call these
// directly, instead call `relate()`, which in turn calls
// these. This is both more uniform but also allows us to add
// additional hooks for other types in the future if needed
// without making older code, which called `relate`, obsolete.
fn tys(&mut self, a: Ty<'tcx>, b: Ty<'tcx>) -> RelateResult<'tcx, Ty<'tcx>>;
fn regions(
&mut self,
a: ty::Region<'tcx>,
b: ty::Region<'tcx>,
) -> RelateResult<'tcx, ty::Region<'tcx>>;
fn consts(
&mut self,
a: ty::Const<'tcx>,
b: ty::Const<'tcx>,
) -> RelateResult<'tcx, ty::Const<'tcx>>;
fn binders<T>(
&mut self,
a: ty::Binder<'tcx, T>,
b: ty::Binder<'tcx, T>,
) -> RelateResult<'tcx, ty::Binder<'tcx, T>>
where
T: Relate<'tcx>;
/// Whether aliases should be related structurally or not. Used
/// to adjust the behavior of generalization and combine.
///
/// This should always be `No` unless in a few special-cases when
/// instantiating canonical responses and in the new solver. Each
/// such case should have a comment explaining why it is used.
#[derive(Debug, Copy, Clone)]
pub enum StructurallyRelateAliases {
Yes,
No,
}
pub trait Relate<'tcx>: TypeFoldable<TyCtxt<'tcx>> + PartialEq + Copy {
fn relate<R: TypeRelation<'tcx>>(
relation: &mut R,
a: Self,
b: Self,
) -> RelateResult<'tcx, Self>;
}
///////////////////////////////////////////////////////////////////////////
// Relate impls
#[inline]
pub fn relate_args_invariantly<'tcx, R: TypeRelation<'tcx>>(
relation: &mut R,
a_arg: GenericArgsRef<'tcx>,
b_arg: GenericArgsRef<'tcx>,
) -> RelateResult<'tcx, GenericArgsRef<'tcx>> {
relation.tcx().mk_args_from_iter(iter::zip(a_arg, b_arg).map(|(a, b)| {
relation.relate_with_variance(ty::Invariant, ty::VarianceDiagInfo::default(), a, b)
}))
}
pub fn relate_args_with_variances<'tcx, R: TypeRelation<'tcx>>(
relation: &mut R,
ty_def_id: DefId,
variances: &[ty::Variance],
a_arg: GenericArgsRef<'tcx>,
b_arg: GenericArgsRef<'tcx>,
fetch_ty_for_diag: bool,
) -> RelateResult<'tcx, GenericArgsRef<'tcx>> {
let tcx = relation.tcx();
let mut cached_ty = None;
let params = iter::zip(a_arg, b_arg).enumerate().map(|(i, (a, b))| {
let variance = variances[i];
let variance_info = if variance == ty::Invariant && fetch_ty_for_diag {
let ty =
*cached_ty.get_or_insert_with(|| tcx.type_of(ty_def_id).instantiate(tcx, a_arg));
ty::VarianceDiagInfo::Invariant { ty, param_index: i.try_into().unwrap() }
} else {
ty::VarianceDiagInfo::default()
};
relation.relate_with_variance(variance, variance_info, a, b)
});
tcx.mk_args_from_iter(params)
}
impl<'tcx> Relate<'tcx> for ty::FnSig<'tcx> {
fn relate<R: TypeRelation<'tcx>>(
relation: &mut R,
a: ty::FnSig<'tcx>,
b: ty::FnSig<'tcx>,
) -> RelateResult<'tcx, ty::FnSig<'tcx>> {
let tcx = relation.tcx();
if a.c_variadic != b.c_variadic {
return Err(TypeError::VariadicMismatch(expected_found(a.c_variadic, b.c_variadic)));
}
let safety = relation.relate(a.safety, b.safety)?;
let abi = relation.relate(a.abi, b.abi)?;
if a.inputs().len() != b.inputs().len() {
return Err(TypeError::ArgCount);
}
let inputs_and_output = iter::zip(a.inputs(), b.inputs())
.map(|(&a, &b)| ((a, b), false))
.chain(iter::once(((a.output(), b.output()), true)))
.map(|((a, b), is_output)| {
if is_output {
relation.relate(a, b)
} else {
relation.relate_with_variance(
ty::Contravariant,
ty::VarianceDiagInfo::default(),
a,
b,
)
}
})
.enumerate()
.map(|(i, r)| match r {
Err(TypeError::Sorts(exp_found) | TypeError::ArgumentSorts(exp_found, _)) => {
Err(TypeError::ArgumentSorts(exp_found, i))
}
Err(TypeError::Mutability | TypeError::ArgumentMutability(_)) => {
Err(TypeError::ArgumentMutability(i))
}
r => r,
});
Ok(ty::FnSig {
inputs_and_output: tcx.mk_type_list_from_iter(inputs_and_output)?,
c_variadic: a.c_variadic,
safety,
abi,
})
}
}
impl<'tcx> Relate<'tcx> for ty::BoundConstness {
fn relate<R: TypeRelation<'tcx>>(
_relation: &mut R,
a: ty::BoundConstness,
b: ty::BoundConstness,
) -> RelateResult<'tcx, ty::BoundConstness> {
if a != b { Err(TypeError::ConstnessMismatch(expected_found(a, b))) } else { Ok(a) }
}
}
impl<'tcx> Relate<'tcx> for hir::Safety {
fn relate<R: TypeRelation<'tcx>>(
_relation: &mut R,
a: hir::Safety,
b: hir::Safety,
) -> RelateResult<'tcx, hir::Safety> {
if a != b { Err(TypeError::SafetyMismatch(expected_found(a, b))) } else { Ok(a) }
}
}
impl<'tcx> Relate<'tcx> for abi::Abi {
fn relate<R: TypeRelation<'tcx>>(
_relation: &mut R,
a: abi::Abi,
b: abi::Abi,
) -> RelateResult<'tcx, abi::Abi> {
if a == b { Ok(a) } else { Err(TypeError::AbiMismatch(expected_found(a, b))) }
}
}
impl<'tcx> Relate<'tcx> for ty::AliasTy<'tcx> {
fn relate<R: TypeRelation<'tcx>>(
relation: &mut R,
a: ty::AliasTy<'tcx>,
b: ty::AliasTy<'tcx>,
) -> RelateResult<'tcx, ty::AliasTy<'tcx>> {
if a.def_id != b.def_id {
Err(TypeError::ProjectionMismatched(expected_found(a.def_id, b.def_id)))
} else {
let args = match a.kind(relation.tcx()) {
ty::Opaque => relate_args_with_variances(
relation,
a.def_id,
relation.tcx().variances_of(a.def_id),
a.args,
b.args,
false, // do not fetch `type_of(a_def_id)`, as it will cause a cycle
)?,
ty::Projection | ty::Weak | ty::Inherent => {
relate_args_invariantly(relation, a.args, b.args)?
}
};
Ok(ty::AliasTy::new(relation.tcx(), a.def_id, args))
}
}
}
impl<'tcx> Relate<'tcx> for ty::AliasTerm<'tcx> {
fn relate<R: TypeRelation<'tcx>>(
relation: &mut R,
a: ty::AliasTerm<'tcx>,
b: ty::AliasTerm<'tcx>,
) -> RelateResult<'tcx, ty::AliasTerm<'tcx>> {
if a.def_id != b.def_id {
Err(TypeError::ProjectionMismatched(expected_found(a.def_id, b.def_id)))
} else {
let args = match a.kind(relation.tcx()) {
ty::AliasTermKind::OpaqueTy => relate_args_with_variances(
relation,
a.def_id,
relation.tcx().variances_of(a.def_id),
a.args,
b.args,
false, // do not fetch `type_of(a_def_id)`, as it will cause a cycle
)?,
ty::AliasTermKind::ProjectionTy
| ty::AliasTermKind::WeakTy
| ty::AliasTermKind::InherentTy
| ty::AliasTermKind::UnevaluatedConst
| ty::AliasTermKind::ProjectionConst => {
relate_args_invariantly(relation, a.args, b.args)?
}
};
Ok(ty::AliasTerm::new(relation.tcx(), a.def_id, args))
}
}
}
impl<'tcx> Relate<'tcx> for ty::ExistentialProjection<'tcx> {
fn relate<R: TypeRelation<'tcx>>(
relation: &mut R,
a: ty::ExistentialProjection<'tcx>,
b: ty::ExistentialProjection<'tcx>,
) -> RelateResult<'tcx, ty::ExistentialProjection<'tcx>> {
if a.def_id != b.def_id {
Err(TypeError::ProjectionMismatched(expected_found(a.def_id, b.def_id)))
} else {
let term = relation.relate_with_variance(
ty::Invariant,
ty::VarianceDiagInfo::default(),
a.term,
b.term,
)?;
let args = relation.relate_with_variance(
ty::Invariant,
ty::VarianceDiagInfo::default(),
a.args,
b.args,
)?;
Ok(ty::ExistentialProjection { def_id: a.def_id, args, term })
}
}
}
impl<'tcx> Relate<'tcx> for ty::TraitRef<'tcx> {
fn relate<R: TypeRelation<'tcx>>(
relation: &mut R,
a: ty::TraitRef<'tcx>,
b: ty::TraitRef<'tcx>,
) -> RelateResult<'tcx, ty::TraitRef<'tcx>> {
// Different traits cannot be related.
if a.def_id != b.def_id {
Err(TypeError::Traits(expected_found(a.def_id, b.def_id)))
} else {
let args = relate_args_invariantly(relation, a.args, b.args)?;
Ok(ty::TraitRef::new(relation.tcx(), a.def_id, args))
}
}
}
impl<'tcx> Relate<'tcx> for ty::ExistentialTraitRef<'tcx> {
fn relate<R: TypeRelation<'tcx>>(
relation: &mut R,
a: ty::ExistentialTraitRef<'tcx>,
b: ty::ExistentialTraitRef<'tcx>,
) -> RelateResult<'tcx, ty::ExistentialTraitRef<'tcx>> {
// Different traits cannot be related.
if a.def_id != b.def_id {
Err(TypeError::Traits(expected_found(a.def_id, b.def_id)))
} else {
let args = relate_args_invariantly(relation, a.args, b.args)?;
Ok(ty::ExistentialTraitRef { def_id: a.def_id, args })
}
}
}
#[derive(PartialEq, Copy, Debug, Clone, TypeFoldable, TypeVisitable)]
struct CoroutineWitness<'tcx>(&'tcx ty::List<Ty<'tcx>>);
impl<'tcx> Relate<'tcx> for CoroutineWitness<'tcx> {
fn relate<R: TypeRelation<'tcx>>(
relation: &mut R,
a: CoroutineWitness<'tcx>,
b: CoroutineWitness<'tcx>,
) -> RelateResult<'tcx, CoroutineWitness<'tcx>> {
assert_eq!(a.0.len(), b.0.len());
let tcx = relation.tcx();
let types =
tcx.mk_type_list_from_iter(iter::zip(a.0, b.0).map(|(a, b)| relation.relate(a, b)))?;
Ok(CoroutineWitness(types))
}
}
impl<'tcx> Relate<'tcx> for ImplSubject<'tcx> {
impl<'tcx> Relate<TyCtxt<'tcx>> for ty::ImplSubject<'tcx> {
#[inline]
fn relate<R: TypeRelation<'tcx>>(
fn relate<R: TypeRelation<TyCtxt<'tcx>>>(
relation: &mut R,
a: ImplSubject<'tcx>,
b: ImplSubject<'tcx>,
) -> RelateResult<'tcx, ImplSubject<'tcx>> {
a: ty::ImplSubject<'tcx>,
b: ty::ImplSubject<'tcx>,
) -> RelateResult<'tcx, ty::ImplSubject<'tcx>> {
match (a, b) {
(ImplSubject::Trait(trait_ref_a), ImplSubject::Trait(trait_ref_b)) => {
(ty::ImplSubject::Trait(trait_ref_a), ty::ImplSubject::Trait(trait_ref_b)) => {
let trait_ref = ty::TraitRef::relate(relation, trait_ref_a, trait_ref_b)?;
Ok(ImplSubject::Trait(trait_ref))
Ok(ty::ImplSubject::Trait(trait_ref))
}
(ImplSubject::Inherent(ty_a), ImplSubject::Inherent(ty_b)) => {
(ty::ImplSubject::Inherent(ty_a), ty::ImplSubject::Inherent(ty_b)) => {
let ty = Ty::relate(relation, ty_a, ty_b)?;
Ok(ImplSubject::Inherent(ty))
Ok(ty::ImplSubject::Inherent(ty))
}
(ImplSubject::Trait(_), ImplSubject::Inherent(_))
| (ImplSubject::Inherent(_), ImplSubject::Trait(_)) => {
(ty::ImplSubject::Trait(_), ty::ImplSubject::Inherent(_))
| (ty::ImplSubject::Inherent(_), ty::ImplSubject::Trait(_)) => {
bug!("can not relate TraitRef and Ty");
}
}
}
}
impl<'tcx> Relate<'tcx> for Ty<'tcx> {
impl<'tcx> Relate<TyCtxt<'tcx>> for Ty<'tcx> {
#[inline]
fn relate<R: TypeRelation<'tcx>>(
fn relate<R: TypeRelation<TyCtxt<'tcx>>>(
relation: &mut R,
a: Ty<'tcx>,
b: Ty<'tcx>,
@ -386,9 +57,9 @@ fn relate<R: TypeRelation<'tcx>>(
}
}
impl<'tcx> Relate<'tcx> for Pattern<'tcx> {
impl<'tcx> Relate<TyCtxt<'tcx>> for ty::Pattern<'tcx> {
#[inline]
fn relate<R: TypeRelation<'tcx>>(
fn relate<R: TypeRelation<TyCtxt<'tcx>>>(
relation: &mut R,
a: Self,
b: Self,
@ -416,276 +87,8 @@ fn relate<R: TypeRelation<'tcx>>(
}
}
/// Relates `a` and `b` structurally, calling the relation for all nested values.
/// Any semantic equality, e.g. of projections, and inference variables have to be
/// handled by the caller.
#[instrument(level = "trace", skip(relation), ret)]
pub fn structurally_relate_tys<'tcx, R: TypeRelation<'tcx>>(
relation: &mut R,
a: Ty<'tcx>,
b: Ty<'tcx>,
) -> RelateResult<'tcx, Ty<'tcx>> {
let tcx = relation.tcx();
match (a.kind(), b.kind()) {
(&ty::Infer(_), _) | (_, &ty::Infer(_)) => {
// The caller should handle these cases!
bug!("var types encountered in structurally_relate_tys")
}
(ty::Bound(..), _) | (_, ty::Bound(..)) => {
bug!("bound types encountered in structurally_relate_tys")
}
(&ty::Error(guar), _) | (_, &ty::Error(guar)) => Ok(Ty::new_error(tcx, guar)),
(&ty::Never, _)
| (&ty::Char, _)
| (&ty::Bool, _)
| (&ty::Int(_), _)
| (&ty::Uint(_), _)
| (&ty::Float(_), _)
| (&ty::Str, _)
if a == b =>
{
Ok(a)
}
(ty::Param(a_p), ty::Param(b_p)) if a_p.index == b_p.index => {
debug_assert_eq!(a_p.name, b_p.name, "param types with same index differ in name");
Ok(a)
}
(ty::Placeholder(p1), ty::Placeholder(p2)) if p1 == p2 => Ok(a),
(&ty::Adt(a_def, a_args), &ty::Adt(b_def, b_args)) if a_def == b_def => {
let args = relation.relate_item_args(a_def.did(), a_args, b_args)?;
Ok(Ty::new_adt(tcx, a_def, args))
}
(&ty::Foreign(a_id), &ty::Foreign(b_id)) if a_id == b_id => Ok(Ty::new_foreign(tcx, a_id)),
(&ty::Dynamic(a_obj, a_region, a_repr), &ty::Dynamic(b_obj, b_region, b_repr))
if a_repr == b_repr =>
{
Ok(Ty::new_dynamic(
tcx,
relation.relate(a_obj, b_obj)?,
relation.relate(a_region, b_region)?,
a_repr,
))
}
(&ty::Coroutine(a_id, a_args), &ty::Coroutine(b_id, b_args)) if a_id == b_id => {
// All Coroutine types with the same id represent
// the (anonymous) type of the same coroutine expression. So
// all of their regions should be equated.
let args = relate_args_invariantly(relation, a_args, b_args)?;
Ok(Ty::new_coroutine(tcx, a_id, args))
}
(&ty::CoroutineWitness(a_id, a_args), &ty::CoroutineWitness(b_id, b_args))
if a_id == b_id =>
{
// All CoroutineWitness types with the same id represent
// the (anonymous) type of the same coroutine expression. So
// all of their regions should be equated.
let args = relate_args_invariantly(relation, a_args, b_args)?;
Ok(Ty::new_coroutine_witness(tcx, a_id, args))
}
(&ty::Closure(a_id, a_args), &ty::Closure(b_id, b_args)) if a_id == b_id => {
// All Closure types with the same id represent
// the (anonymous) type of the same closure expression. So
// all of their regions should be equated.
let args = relate_args_invariantly(relation, a_args, b_args)?;
Ok(Ty::new_closure(tcx, a_id, args))
}
(&ty::CoroutineClosure(a_id, a_args), &ty::CoroutineClosure(b_id, b_args))
if a_id == b_id =>
{
let args = relate_args_invariantly(relation, a_args, b_args)?;
Ok(Ty::new_coroutine_closure(tcx, a_id, args))
}
(&ty::RawPtr(a_ty, a_mutbl), &ty::RawPtr(b_ty, b_mutbl)) => {
if a_mutbl != b_mutbl {
return Err(TypeError::Mutability);
}
let (variance, info) = match a_mutbl {
hir::Mutability::Not => (ty::Covariant, ty::VarianceDiagInfo::None),
hir::Mutability::Mut => {
(ty::Invariant, ty::VarianceDiagInfo::Invariant { ty: a, param_index: 0 })
}
};
let ty = relation.relate_with_variance(variance, info, a_ty, b_ty)?;
Ok(Ty::new_ptr(tcx, ty, a_mutbl))
}
(&ty::Ref(a_r, a_ty, a_mutbl), &ty::Ref(b_r, b_ty, b_mutbl)) => {
if a_mutbl != b_mutbl {
return Err(TypeError::Mutability);
}
let (variance, info) = match a_mutbl {
hir::Mutability::Not => (ty::Covariant, ty::VarianceDiagInfo::None),
hir::Mutability::Mut => {
(ty::Invariant, ty::VarianceDiagInfo::Invariant { ty: a, param_index: 0 })
}
};
let r = relation.relate(a_r, b_r)?;
let ty = relation.relate_with_variance(variance, info, a_ty, b_ty)?;
Ok(Ty::new_ref(tcx, r, ty, a_mutbl))
}
(&ty::Array(a_t, sz_a), &ty::Array(b_t, sz_b)) => {
let t = relation.relate(a_t, b_t)?;
match relation.relate(sz_a, sz_b) {
Ok(sz) => Ok(Ty::new_array_with_const_len(tcx, t, sz)),
Err(err) => {
// Check whether the lengths are both concrete/known values,
// but are unequal, for better diagnostics.
let sz_a = sz_a.try_to_target_usize(tcx);
let sz_b = sz_b.try_to_target_usize(tcx);
match (sz_a, sz_b) {
(Some(sz_a_val), Some(sz_b_val)) if sz_a_val != sz_b_val => {
Err(TypeError::FixedArraySize(expected_found(sz_a_val, sz_b_val)))
}
_ => Err(err),
}
}
}
}
(&ty::Slice(a_t), &ty::Slice(b_t)) => {
let t = relation.relate(a_t, b_t)?;
Ok(Ty::new_slice(tcx, t))
}
(&ty::Tuple(as_), &ty::Tuple(bs)) => {
if as_.len() == bs.len() {
Ok(Ty::new_tup_from_iter(
tcx,
iter::zip(as_, bs).map(|(a, b)| relation.relate(a, b)),
)?)
} else if !(as_.is_empty() || bs.is_empty()) {
Err(TypeError::TupleSize(expected_found(as_.len(), bs.len())))
} else {
Err(TypeError::Sorts(expected_found(a, b)))
}
}
(&ty::FnDef(a_def_id, a_args), &ty::FnDef(b_def_id, b_args)) if a_def_id == b_def_id => {
let args = relation.relate_item_args(a_def_id, a_args, b_args)?;
Ok(Ty::new_fn_def(tcx, a_def_id, args))
}
(&ty::FnPtr(a_fty), &ty::FnPtr(b_fty)) => {
let fty = relation.relate(a_fty, b_fty)?;
Ok(Ty::new_fn_ptr(tcx, fty))
}
// Alias tend to mostly already be handled downstream due to normalization.
(&ty::Alias(a_kind, a_data), &ty::Alias(b_kind, b_data)) => {
let alias_ty = relation.relate(a_data, b_data)?;
assert_eq!(a_kind, b_kind);
Ok(Ty::new_alias(tcx, a_kind, alias_ty))
}
(&ty::Pat(a_ty, a_pat), &ty::Pat(b_ty, b_pat)) => {
let ty = relation.relate(a_ty, b_ty)?;
let pat = relation.relate(a_pat, b_pat)?;
Ok(Ty::new_pat(tcx, ty, pat))
}
_ => Err(TypeError::Sorts(expected_found(a, b))),
}
}
/// Relates `a` and `b` structurally, calling the relation for all nested values.
/// Any semantic equality, e.g. of unevaluated consts, and inference variables have
/// to be handled by the caller.
///
/// FIXME: This is not totally structual, which probably should be fixed.
/// See the HACKs below.
pub fn structurally_relate_consts<'tcx, R: TypeRelation<'tcx>>(
relation: &mut R,
mut a: ty::Const<'tcx>,
mut b: ty::Const<'tcx>,
) -> RelateResult<'tcx, ty::Const<'tcx>> {
debug!("{}.structurally_relate_consts(a = {:?}, b = {:?})", relation.tag(), a, b);
let tcx = relation.tcx();
if tcx.features().generic_const_exprs {
a = tcx.expand_abstract_consts(a);
b = tcx.expand_abstract_consts(b);
}
debug!("{}.structurally_relate_consts(normed_a = {:?}, normed_b = {:?})", relation.tag(), a, b);
// Currently, the values that can be unified are primitive types,
// and those that derive both `PartialEq` and `Eq`, corresponding
// to structural-match types.
let is_match = match (a.kind(), b.kind()) {
(ty::ConstKind::Infer(_), _) | (_, ty::ConstKind::Infer(_)) => {
// The caller should handle these cases!
bug!("var types encountered in structurally_relate_consts: {:?} {:?}", a, b)
}
(ty::ConstKind::Error(_), _) => return Ok(a),
(_, ty::ConstKind::Error(_)) => return Ok(b),
(ty::ConstKind::Param(a_p), ty::ConstKind::Param(b_p)) if a_p.index == b_p.index => {
debug_assert_eq!(a_p.name, b_p.name, "param types with same index differ in name");
true
}
(ty::ConstKind::Placeholder(p1), ty::ConstKind::Placeholder(p2)) => p1 == p2,
(ty::ConstKind::Value(_, a_val), ty::ConstKind::Value(_, b_val)) => a_val == b_val,
// While this is slightly incorrect, it shouldn't matter for `min_const_generics`
// and is the better alternative to waiting until `generic_const_exprs` can
// be stabilized.
(ty::ConstKind::Unevaluated(au), ty::ConstKind::Unevaluated(bu)) if au.def == bu.def => {
if cfg!(debug_assertions) {
let a_ty = tcx.type_of(au.def).instantiate(tcx, au.args);
let b_ty = tcx.type_of(bu.def).instantiate(tcx, bu.args);
assert_eq!(a_ty, b_ty);
}
let args = relation.relate_with_variance(
ty::Variance::Invariant,
ty::VarianceDiagInfo::default(),
au.args,
bu.args,
)?;
return Ok(ty::Const::new_unevaluated(tcx, ty::UnevaluatedConst { def: au.def, args }));
}
(ty::ConstKind::Expr(ae), ty::ConstKind::Expr(be)) => {
match (ae.kind, be.kind) {
(ty::ExprKind::Binop(a_binop), ty::ExprKind::Binop(b_binop))
if a_binop == b_binop => {}
(ty::ExprKind::UnOp(a_unop), ty::ExprKind::UnOp(b_unop)) if a_unop == b_unop => {}
(ty::ExprKind::FunctionCall, ty::ExprKind::FunctionCall) => {}
(ty::ExprKind::Cast(a_kind), ty::ExprKind::Cast(b_kind)) if a_kind == b_kind => {}
_ => return Err(TypeError::ConstMismatch(expected_found(a, b))),
}
let args = relation.relate(ae.args(), be.args())?;
return Ok(ty::Const::new_expr(tcx, ty::Expr::new(ae.kind, args)));
}
_ => false,
};
if is_match { Ok(a) } else { Err(TypeError::ConstMismatch(expected_found(a, b))) }
}
impl<'tcx> Relate<'tcx> for &'tcx ty::List<ty::PolyExistentialPredicate<'tcx>> {
fn relate<R: TypeRelation<'tcx>>(
impl<'tcx> Relate<TyCtxt<'tcx>> for &'tcx ty::List<ty::PolyExistentialPredicate<'tcx>> {
fn relate<R: TypeRelation<TyCtxt<'tcx>>>(
relation: &mut R,
a: Self,
b: Self,
@ -703,44 +106,65 @@ fn relate<R: TypeRelation<'tcx>>(
b_v.sort_by(|a, b| a.skip_binder().stable_cmp(tcx, &b.skip_binder()));
b_v.dedup();
if a_v.len() != b_v.len() {
return Err(TypeError::ExistentialMismatch(expected_found(a, b)));
return Err(TypeError::ExistentialMismatch(ExpectedFound::new(true, a, b)));
}
let v = iter::zip(a_v, b_v).map(|(ep_a, ep_b)| {
match (ep_a.skip_binder(), ep_b.skip_binder()) {
(ExistentialPredicate::Trait(a), ExistentialPredicate::Trait(b)) => Ok(ep_a
.rebind(ExistentialPredicate::Trait(
relation.relate(ep_a.rebind(a), ep_b.rebind(b))?.skip_binder(),
))),
(ExistentialPredicate::Projection(a), ExistentialPredicate::Projection(b)) => {
Ok(ep_a.rebind(ExistentialPredicate::Projection(
(ty::ExistentialPredicate::Trait(a), ty::ExistentialPredicate::Trait(b)) => {
Ok(ep_a.rebind(ty::ExistentialPredicate::Trait(
relation.relate(ep_a.rebind(a), ep_b.rebind(b))?.skip_binder(),
)))
}
(ExistentialPredicate::AutoTrait(a), ExistentialPredicate::AutoTrait(b))
if a == b =>
{
Ok(ep_a.rebind(ExistentialPredicate::AutoTrait(a)))
}
_ => Err(TypeError::ExistentialMismatch(expected_found(a, b))),
(
ty::ExistentialPredicate::Projection(a),
ty::ExistentialPredicate::Projection(b),
) => Ok(ep_a.rebind(ty::ExistentialPredicate::Projection(
relation.relate(ep_a.rebind(a), ep_b.rebind(b))?.skip_binder(),
))),
(
ty::ExistentialPredicate::AutoTrait(a),
ty::ExistentialPredicate::AutoTrait(b),
) if a == b => Ok(ep_a.rebind(ty::ExistentialPredicate::AutoTrait(a))),
_ => Err(TypeError::ExistentialMismatch(ExpectedFound::new(true, a, b))),
}
});
tcx.mk_poly_existential_predicates_from_iter(v)
}
}
impl<'tcx> Relate<'tcx> for GenericArgsRef<'tcx> {
fn relate<R: TypeRelation<'tcx>>(
impl<'tcx> Relate<TyCtxt<'tcx>> for hir::Safety {
fn relate<R: TypeRelation<TyCtxt<'tcx>>>(
_relation: &mut R,
a: hir::Safety,
b: hir::Safety,
) -> RelateResult<'tcx, hir::Safety> {
if a != b { Err(TypeError::SafetyMismatch(ExpectedFound::new(true, a, b))) } else { Ok(a) }
}
}
impl<'tcx> Relate<TyCtxt<'tcx>> for abi::Abi {
fn relate<R: TypeRelation<TyCtxt<'tcx>>>(
_relation: &mut R,
a: abi::Abi,
b: abi::Abi,
) -> RelateResult<'tcx, abi::Abi> {
if a == b { Ok(a) } else { Err(TypeError::AbiMismatch(ExpectedFound::new(true, a, b))) }
}
}
impl<'tcx> Relate<TyCtxt<'tcx>> for ty::GenericArgsRef<'tcx> {
fn relate<R: TypeRelation<TyCtxt<'tcx>>>(
relation: &mut R,
a: GenericArgsRef<'tcx>,
b: GenericArgsRef<'tcx>,
) -> RelateResult<'tcx, GenericArgsRef<'tcx>> {
a: ty::GenericArgsRef<'tcx>,
b: ty::GenericArgsRef<'tcx>,
) -> RelateResult<'tcx, ty::GenericArgsRef<'tcx>> {
relate_args_invariantly(relation, a, b)
}
}
impl<'tcx> Relate<'tcx> for ty::Region<'tcx> {
fn relate<R: TypeRelation<'tcx>>(
impl<'tcx> Relate<TyCtxt<'tcx>> for ty::Region<'tcx> {
fn relate<R: TypeRelation<TyCtxt<'tcx>>>(
relation: &mut R,
a: ty::Region<'tcx>,
b: ty::Region<'tcx>,
@ -749,8 +173,8 @@ fn relate<R: TypeRelation<'tcx>>(
}
}
impl<'tcx> Relate<'tcx> for ty::Const<'tcx> {
fn relate<R: TypeRelation<'tcx>>(
impl<'tcx> Relate<TyCtxt<'tcx>> for ty::Const<'tcx> {
fn relate<R: TypeRelation<TyCtxt<'tcx>>>(
relation: &mut R,
a: ty::Const<'tcx>,
b: ty::Const<'tcx>,
@ -759,85 +183,70 @@ fn relate<R: TypeRelation<'tcx>>(
}
}
impl<'tcx, T: Relate<'tcx>> Relate<'tcx> for ty::Binder<'tcx, T> {
fn relate<R: TypeRelation<'tcx>>(
impl<'tcx> Relate<TyCtxt<'tcx>> for ty::Expr<'tcx> {
fn relate<R: TypeRelation<TyCtxt<'tcx>>>(
relation: &mut R,
a: ty::Binder<'tcx, T>,
b: ty::Binder<'tcx, T>,
) -> RelateResult<'tcx, ty::Binder<'tcx, T>> {
relation.binders(a, b)
ae: ty::Expr<'tcx>,
be: ty::Expr<'tcx>,
) -> RelateResult<'tcx, ty::Expr<'tcx>> {
// FIXME(generic_const_exprs): is it possible to relate two consts which are not identical
// exprs? Should we care about that?
// FIXME(generic_const_exprs): relating the `ty()`s is a little weird since it is supposed to
// ICE If they mismatch. Unfortunately `ConstKind::Expr` is a little special and can be thought
// of as being generic over the argument types, however this is implicit so these types don't get
// related when we relate the args of the item this const arg is for.
match (ae.kind, be.kind) {
(ty::ExprKind::Binop(a_binop), ty::ExprKind::Binop(b_binop)) if a_binop == b_binop => {}
(ty::ExprKind::UnOp(a_unop), ty::ExprKind::UnOp(b_unop)) if a_unop == b_unop => {}
(ty::ExprKind::FunctionCall, ty::ExprKind::FunctionCall) => {}
(ty::ExprKind::Cast(a_kind), ty::ExprKind::Cast(b_kind)) if a_kind == b_kind => {}
_ => return Err(TypeError::Mismatch),
}
let args = relation.relate(ae.args(), be.args())?;
Ok(ty::Expr::new(ae.kind, args))
}
}
impl<'tcx> Relate<'tcx> for GenericArg<'tcx> {
fn relate<R: TypeRelation<'tcx>>(
impl<'tcx> Relate<TyCtxt<'tcx>> for ty::GenericArg<'tcx> {
fn relate<R: TypeRelation<TyCtxt<'tcx>>>(
relation: &mut R,
a: GenericArg<'tcx>,
b: GenericArg<'tcx>,
) -> RelateResult<'tcx, GenericArg<'tcx>> {
a: ty::GenericArg<'tcx>,
b: ty::GenericArg<'tcx>,
) -> RelateResult<'tcx, ty::GenericArg<'tcx>> {
match (a.unpack(), b.unpack()) {
(GenericArgKind::Lifetime(a_lt), GenericArgKind::Lifetime(b_lt)) => {
(ty::GenericArgKind::Lifetime(a_lt), ty::GenericArgKind::Lifetime(b_lt)) => {
Ok(relation.relate(a_lt, b_lt)?.into())
}
(GenericArgKind::Type(a_ty), GenericArgKind::Type(b_ty)) => {
(ty::GenericArgKind::Type(a_ty), ty::GenericArgKind::Type(b_ty)) => {
Ok(relation.relate(a_ty, b_ty)?.into())
}
(GenericArgKind::Const(a_ct), GenericArgKind::Const(b_ct)) => {
(ty::GenericArgKind::Const(a_ct), ty::GenericArgKind::Const(b_ct)) => {
Ok(relation.relate(a_ct, b_ct)?.into())
}
(GenericArgKind::Lifetime(unpacked), x) => {
(ty::GenericArgKind::Lifetime(unpacked), x) => {
bug!("impossible case reached: can't relate: {:?} with {:?}", unpacked, x)
}
(GenericArgKind::Type(unpacked), x) => {
(ty::GenericArgKind::Type(unpacked), x) => {
bug!("impossible case reached: can't relate: {:?} with {:?}", unpacked, x)
}
(GenericArgKind::Const(unpacked), x) => {
(ty::GenericArgKind::Const(unpacked), x) => {
bug!("impossible case reached: can't relate: {:?} with {:?}", unpacked, x)
}
}
}
}
impl<'tcx> Relate<'tcx> for ty::PredicatePolarity {
fn relate<R: TypeRelation<'tcx>>(
_relation: &mut R,
a: ty::PredicatePolarity,
b: ty::PredicatePolarity,
) -> RelateResult<'tcx, ty::PredicatePolarity> {
if a != b { Err(TypeError::PolarityMismatch(expected_found(a, b))) } else { Ok(a) }
}
}
impl<'tcx> Relate<'tcx> for ty::TraitPredicate<'tcx> {
fn relate<R: TypeRelation<'tcx>>(
relation: &mut R,
a: ty::TraitPredicate<'tcx>,
b: ty::TraitPredicate<'tcx>,
) -> RelateResult<'tcx, ty::TraitPredicate<'tcx>> {
Ok(ty::TraitPredicate {
trait_ref: relation.relate(a.trait_ref, b.trait_ref)?,
polarity: relation.relate(a.polarity, b.polarity)?,
})
}
}
impl<'tcx> Relate<'tcx> for Term<'tcx> {
fn relate<R: TypeRelation<'tcx>>(
impl<'tcx> Relate<TyCtxt<'tcx>> for ty::Term<'tcx> {
fn relate<R: TypeRelation<TyCtxt<'tcx>>>(
relation: &mut R,
a: Self,
b: Self,
) -> RelateResult<'tcx, Self> {
Ok(match (a.unpack(), b.unpack()) {
(TermKind::Ty(a), TermKind::Ty(b)) => relation.relate(a, b)?.into(),
(TermKind::Const(a), TermKind::Const(b)) => relation.relate(a, b)?.into(),
(ty::TermKind::Ty(a), ty::TermKind::Ty(b)) => relation.relate(a, b)?.into(),
(ty::TermKind::Const(a), ty::TermKind::Const(b)) => relation.relate(a, b)?.into(),
_ => return Err(TypeError::Mismatch),
})
}
}
///////////////////////////////////////////////////////////////////////////
// Error handling
pub fn expected_found<T>(a: T, b: T) -> ExpectedFound<T> {
ExpectedFound::new(true, a, b)
}

View file

@ -296,7 +296,6 @@ fn fmt<Infcx: InferCtxtLike<Interner = TyCtxt<'tcx>>>(
::rustc_target::abi::FieldIdx,
::rustc_target::abi::VariantIdx,
crate::middle::region::Scope,
crate::ty::FloatTy,
::rustc_ast::InlineAsmOptions,
::rustc_ast::InlineAsmTemplatePiece,
::rustc_ast::NodeId,
@ -316,7 +315,7 @@ fn fmt<Infcx: InferCtxtLike<Interner = TyCtxt<'tcx>>>(
crate::traits::Reveal,
crate::ty::adjustment::AutoBorrowMutability,
crate::ty::AdtKind,
crate::ty::BoundConstness,
crate::ty::BoundRegion,
// Including `BoundRegionKind` is a *bit* dubious, but direct
// references to bound region appear in `ty::Error`, and aren't
// really meant to be folded. In general, we can only fold a fully
@ -324,16 +323,11 @@ fn fmt<Infcx: InferCtxtLike<Interner = TyCtxt<'tcx>>>(
crate::ty::BoundRegionKind,
crate::ty::AssocItem,
crate::ty::AssocKind,
crate::ty::AliasTyKind,
crate::ty::Placeholder<crate::ty::BoundRegion>,
crate::ty::Placeholder<crate::ty::BoundTy>,
crate::ty::Placeholder<ty::BoundVar>,
crate::ty::LateParamRegion,
crate::ty::InferTy,
crate::ty::IntVarValue,
crate::ty::adjustment::PointerCoercion,
crate::ty::RegionVid,
crate::ty::Variance,
::rustc_span::Span,
::rustc_span::symbol::Ident,
::rustc_errors::ErrorGuaranteed,

View file

@ -810,6 +810,31 @@ fn new_alias(
Ty::new_alias(interner, kind, alias_ty)
}
fn new_error(interner: TyCtxt<'tcx>, guar: ErrorGuaranteed) -> Self {
Ty::new_error(interner, guar)
}
fn new_adt(
interner: TyCtxt<'tcx>,
adt_def: ty::AdtDef<'tcx>,
args: ty::GenericArgsRef<'tcx>,
) -> Self {
Ty::new_adt(interner, adt_def, args)
}
fn new_foreign(interner: TyCtxt<'tcx>, def_id: DefId) -> Self {
Ty::new_foreign(interner, def_id)
}
fn new_dynamic(
interner: TyCtxt<'tcx>,
preds: &'tcx List<ty::PolyExistentialPredicate<'tcx>>,
region: ty::Region<'tcx>,
kind: ty::DynKind,
) -> Self {
Ty::new_dynamic(interner, preds, region, kind)
}
fn new_coroutine(
interner: TyCtxt<'tcx>,
def_id: DefId,
@ -818,6 +843,51 @@ fn new_coroutine(
Ty::new_coroutine(interner, def_id, args)
}
fn new_coroutine_closure(
interner: TyCtxt<'tcx>,
def_id: DefId,
args: ty::GenericArgsRef<'tcx>,
) -> Self {
Ty::new_coroutine_closure(interner, def_id, args)
}
fn new_closure(interner: TyCtxt<'tcx>, def_id: DefId, args: ty::GenericArgsRef<'tcx>) -> Self {
Ty::new_closure(interner, def_id, args)
}
fn new_coroutine_witness(
interner: TyCtxt<'tcx>,
def_id: DefId,
args: ty::GenericArgsRef<'tcx>,
) -> Self {
Ty::new_coroutine_witness(interner, def_id, args)
}
fn new_ptr(interner: TyCtxt<'tcx>, ty: Self, mutbl: hir::Mutability) -> Self {
Ty::new_ptr(interner, ty, mutbl)
}
fn new_ref(
interner: TyCtxt<'tcx>,
region: ty::Region<'tcx>,
ty: Self,
mutbl: hir::Mutability,
) -> Self {
Ty::new_ref(interner, region, ty, mutbl)
}
fn new_array_with_const_len(interner: TyCtxt<'tcx>, ty: Self, len: ty::Const<'tcx>) -> Self {
Ty::new_array_with_const_len(interner, ty, len)
}
fn new_slice(interner: TyCtxt<'tcx>, ty: Self) -> Self {
Ty::new_slice(interner, ty)
}
fn new_tup(interner: TyCtxt<'tcx>, tys: &[Ty<'tcx>]) -> Self {
Ty::new_tup(interner, tys)
}
fn new_tup_from_iter<It, T>(interner: TyCtxt<'tcx>, iter: It) -> T::Output
where
It: Iterator<Item = T>,
@ -844,6 +914,18 @@ fn from_coroutine_closure_kind(
) -> Self {
Ty::from_coroutine_closure_kind(interner, kind)
}
fn new_fn_def(interner: TyCtxt<'tcx>, def_id: DefId, args: ty::GenericArgsRef<'tcx>) -> Self {
Ty::new_fn_def(interner, def_id, args)
}
fn new_fn_ptr(interner: TyCtxt<'tcx>, sig: ty::Binder<'tcx, ty::FnSig<'tcx>>) -> Self {
Ty::new_fn_ptr(interner, sig)
}
fn new_pat(interner: TyCtxt<'tcx>, ty: Self, pat: ty::Pattern<'tcx>) -> Self {
Ty::new_pat(interner, ty, pat)
}
}
/// Type utilities
@ -1812,43 +1894,6 @@ fn split_inputs_and_output(self) -> (&'tcx [Ty<'tcx>], Ty<'tcx>) {
}
}
/// Extra information about why we ended up with a particular variance.
/// This is only used to add more information to error messages, and
/// has no effect on soundness. While choosing the 'wrong' `VarianceDiagInfo`
/// may lead to confusing notes in error messages, it will never cause
/// a miscompilation or unsoundness.
///
/// When in doubt, use `VarianceDiagInfo::default()`
#[derive(Copy, Clone, Debug, Default, PartialEq, Eq)]
pub enum VarianceDiagInfo<'tcx> {
/// No additional information - this is the default.
/// We will not add any additional information to error messages.
#[default]
None,
/// We switched our variance because a generic argument occurs inside
/// the invariant generic argument of another type.
Invariant {
/// The generic type containing the generic parameter
/// that changes the variance (e.g. `*mut T`, `MyStruct<T>`)
ty: Ty<'tcx>,
/// The index of the generic parameter being used
/// (e.g. `0` for `*mut T`, `1` for `MyStruct<'CovariantParam, 'InvariantParam>`)
param_index: u32,
},
}
impl<'tcx> VarianceDiagInfo<'tcx> {
/// Mirrors `Variance::xform` - used to 'combine' the existing
/// and new `VarianceDiagInfo`s when our variance changes.
pub fn xform(self, other: VarianceDiagInfo<'tcx>) -> VarianceDiagInfo<'tcx> {
// For now, just use the first `VarianceDiagInfo::Invariant` that we see
match self {
VarianceDiagInfo::None => other,
VarianceDiagInfo::Invariant { .. } => self,
}
}
}
// Some types are used a lot. Make sure they don't unintentionally get bigger.
#[cfg(target_pointer_width = "64")]
mod size_asserts {

View file

@ -4,13 +4,16 @@ version = "0.0.0"
edition = "2021"
[dependencies]
rustc_type_ir = { path = "../rustc_type_ir", default-features = false }
# tidy-alphabetical-start
derivative = "2.2.0"
rustc_macros = { path = "../rustc_macros", optional = true }
rustc_type_ir_macros = { path = "../rustc_type_ir_macros" }
rustc_serialize = { path = "../rustc_serialize", optional = true }
rustc_data_structures = { path = "../rustc_data_structures", optional = true }
rustc_ast_ir = { path = "../rustc_ast_ir", default-features = false }
rustc_data_structures = { path = "../rustc_data_structures", optional = true }
rustc_macros = { path = "../rustc_macros", optional = true }
rustc_serialize = { path = "../rustc_serialize", optional = true }
rustc_type_ir = { path = "../rustc_type_ir", default-features = false }
rustc_type_ir_macros = { path = "../rustc_type_ir_macros" }
tracing = "0.1"
# tidy-alphabetical-end
[features]
default = ["nightly"]

View file

@ -7,11 +7,11 @@
// EAGER RESOLUTION
/// Resolves ty, region, and const vars to their inferred values or their root vars.
pub struct EagerResolver<
'a,
pub struct EagerResolver<'a, Infcx, I = <Infcx as InferCtxtLike>::Interner>
where
Infcx: InferCtxtLike<Interner = I>,
I: Interner = <Infcx as InferCtxtLike>::Interner,
> {
I: Interner,
{
infcx: &'a Infcx,
}

View file

@ -622,8 +622,6 @@ parse_or_pattern_not_allowed_in_let_binding = top-level or-patterns are not allo
parse_out_of_range_hex_escape = out of range hex escape
.label = must be a character in the range [\x00-\x7f]
parse_outer_attr_ambiguous = ambiguous outer attributes
parse_outer_attr_explanation = outer attributes, like `#[test]`, annotate the item following them
parse_outer_attribute_not_allowed_on_if_else = outer attributes are not allowed on `if` and `else` branches

View file

@ -495,15 +495,6 @@ pub(crate) struct OuterAttributeNotAllowedOnIfElse {
pub attributes: Span,
}
#[derive(Diagnostic)]
#[diag(parse_outer_attr_ambiguous)]
pub(crate) struct AmbiguousOuterAttributes {
#[primary_span]
pub span: Span,
#[subdiagnostic]
pub sugg: WrapInParentheses,
}
#[derive(Diagnostic)]
#[diag(parse_missing_in_in_for_loop)]
pub(crate) struct MissingInInForLoop {

View file

@ -328,9 +328,7 @@ pub(super) fn parse_expr_assoc_with(
this.parse_expr_assoc_with(prec + prec_adjustment, LhsExpr::NotYetParsed)
})?;
self.error_ambiguous_outer_attrs(&lhs, lhs_span, rhs.span);
let span = lhs_span.to(rhs.span);
let span = self.mk_expr_sp(&lhs, lhs_span, rhs.span);
lhs = match op {
AssocOp::Add
| AssocOp::Subtract
@ -429,18 +427,6 @@ fn error_found_expr_would_be_stmt(&self, lhs: &Expr) {
});
}
fn error_ambiguous_outer_attrs(&self, lhs: &P<Expr>, lhs_span: Span, rhs_span: Span) {
if let Some(attr) = lhs.attrs.iter().find(|a| a.style == AttrStyle::Outer) {
self.dcx().emit_err(errors::AmbiguousOuterAttributes {
span: attr.span.to(rhs_span),
sugg: errors::WrapInParentheses::Expression {
left: attr.span.shrink_to_lo(),
right: lhs_span.shrink_to_hi(),
},
});
}
}
/// Possibly translate the current token to an associative operator.
/// The method does not advance the current token.
///
@ -520,8 +506,7 @@ fn parse_expr_range(
None
};
let rhs_span = rhs.as_ref().map_or(cur_op_span, |x| x.span);
self.error_ambiguous_outer_attrs(&lhs, lhs.span, rhs_span);
let span = lhs.span.to(rhs_span);
let span = self.mk_expr_sp(&lhs, lhs.span, rhs_span);
let limits =
if op == AssocOp::DotDot { RangeLimits::HalfOpen } else { RangeLimits::Closed };
let range = self.mk_range(Some(lhs), rhs, limits);
@ -739,8 +724,7 @@ fn parse_assoc_op_cast(
expr_kind: fn(P<Expr>, P<Ty>) -> ExprKind,
) -> PResult<'a, P<Expr>> {
let mk_expr = |this: &mut Self, lhs: P<Expr>, rhs: P<Ty>| {
this.error_ambiguous_outer_attrs(&lhs, lhs_span, rhs.span);
this.mk_expr(lhs_span.to(rhs.span), expr_kind(lhs, rhs))
this.mk_expr(this.mk_expr_sp(&lhs, lhs_span, rhs.span), expr_kind(lhs, rhs))
};
// Save the state of the parser before parsing type normally, in case there is a
@ -3858,6 +3842,16 @@ pub(super) fn mk_expr_err(&self, span: Span, guar: ErrorGuaranteed) -> P<Expr> {
self.mk_expr(span, ExprKind::Err(guar))
}
/// Create expression span ensuring the span of the parent node
/// is larger than the span of lhs and rhs, including the attributes.
fn mk_expr_sp(&self, lhs: &P<Expr>, lhs_span: Span, rhs_span: Span) -> Span {
lhs.attrs
.iter()
.find(|a| a.style == AttrStyle::Outer)
.map_or(lhs_span, |a| a.span)
.to(rhs_span)
}
fn collect_tokens_for_expr(
&mut self,
attrs: AttrWrapper,

View file

@ -12,7 +12,7 @@
pub struct FileSearch<'a> {
sysroot: &'a Path,
triple: &'a str,
search_paths: &'a [SearchPath],
cli_search_paths: &'a [SearchPath],
tlib_path: &'a SearchPath,
kind: PathKind,
}
@ -20,7 +20,7 @@ pub struct FileSearch<'a> {
impl<'a> FileSearch<'a> {
pub fn search_paths(&self) -> impl Iterator<Item = &'a SearchPath> {
let kind = self.kind;
self.search_paths
self.cli_search_paths
.iter()
.filter(move |sp| sp.kind.matches(kind))
.chain(std::iter::once(self.tlib_path))
@ -37,26 +37,26 @@ pub fn get_self_contained_lib_path(&self) -> PathBuf {
pub fn new(
sysroot: &'a Path,
triple: &'a str,
search_paths: &'a [SearchPath],
cli_search_paths: &'a [SearchPath],
tlib_path: &'a SearchPath,
kind: PathKind,
) -> FileSearch<'a> {
debug!("using sysroot = {}, triple = {}", sysroot.display(), triple);
FileSearch { sysroot, triple, search_paths, tlib_path, kind }
FileSearch { sysroot, triple, cli_search_paths, tlib_path, kind }
}
}
pub fn make_target_lib_path(sysroot: &Path, target_triple: &str) -> PathBuf {
let rustlib_path = rustc_target::target_rustlib_path(sysroot, target_triple);
PathBuf::from_iter([sysroot, Path::new(&rustlib_path), Path::new("lib")])
let rustlib_path = rustc_target::relative_target_rustlib_path(sysroot, target_triple);
sysroot.join(rustlib_path).join("lib")
}
/// Returns a path to the target's `bin` folder within its `rustlib` path in the sysroot. This is
/// where binaries are usually installed, e.g. the self-contained linkers, lld-wrappers, LLVM tools,
/// etc.
pub fn make_target_bin_path(sysroot: &Path, target_triple: &str) -> PathBuf {
let rustlib_path = rustc_target::target_rustlib_path(sysroot, target_triple);
PathBuf::from_iter([sysroot, Path::new(&rustlib_path), Path::new("bin")])
let rustlib_path = rustc_target::relative_target_rustlib_path(sysroot, target_triple);
sysroot.join(rustlib_path).join("bin")
}
#[cfg(unix)]
@ -275,7 +275,7 @@ fn from_env_args_next() -> Option<PathBuf> {
p.pop();
p.pop();
// Look for the target rustlib directory in the suspected sysroot.
let mut rustlib_path = rustc_target::target_rustlib_path(&p, "dummy");
let mut rustlib_path = rustc_target::relative_target_rustlib_path(&p, "dummy");
rustlib_path.pop(); // pop off the dummy target.
rustlib_path.exists().then_some(p)
}

View file

@ -41,17 +41,13 @@
///
/// For example: `target_sysroot_path("/usr", "x86_64-unknown-linux-gnu")` =>
/// `"lib*/rustlib/x86_64-unknown-linux-gnu"`.
pub fn target_rustlib_path(sysroot: &Path, target_triple: &str) -> PathBuf {
let libdir = find_libdir(sysroot);
PathBuf::from_iter([
Path::new(libdir.as_ref()),
Path::new(RUST_LIB_DIR),
Path::new(target_triple),
])
pub fn relative_target_rustlib_path(sysroot: &Path, target_triple: &str) -> PathBuf {
let libdir = find_relative_libdir(sysroot);
Path::new(libdir.as_ref()).join(RUST_LIB_DIR).join(target_triple)
}
/// The name of the directory rustc expects libraries to be located.
fn find_libdir(sysroot: &Path) -> std::borrow::Cow<'static, str> {
fn find_relative_libdir(sysroot: &Path) -> std::borrow::Cow<'static, str> {
// FIXME: This is a quick hack to make the rustc binary able to locate
// Rust libraries in Linux environments where libraries might be installed
// to lib64/lib32. This would be more foolproof by basing the sysroot off

View file

@ -3367,7 +3367,7 @@ fn load_file(path: &Path) -> Result<(Target, TargetWarnings), String> {
// Additionally look in the sysroot under `lib/rustlib/<triple>/target.json`
// as a fallback.
let rustlib_path = crate::target_rustlib_path(sysroot, target_triple);
let rustlib_path = crate::relative_target_rustlib_path(sysroot, target_triple);
let p = PathBuf::from_iter([
Path::new(sysroot),
Path::new(&rustlib_path),

View file

@ -37,11 +37,11 @@
mod probe;
mod select;
pub struct EvalCtxt<
'a,
pub struct EvalCtxt<'a, Infcx, I = <Infcx as InferCtxtLike>::Interner>
where
Infcx: InferCtxtLike<Interner = I>,
I: Interner = <Infcx as InferCtxtLike>::Interner,
> {
I: Interner,
{
/// The inference context that backs (mostly) inference and placeholder terms
/// instantiated while solving goals.
///

View file

@ -28,7 +28,7 @@
use rustc_macros::extension;
use rustc_middle::hir::map;
use rustc_middle::traits::IsConstable;
use rustc_middle::ty::error::TypeError::{self, Sorts};
use rustc_middle::ty::error::TypeError;
use rustc_middle::ty::print::PrintPolyTraitRefExt;
use rustc_middle::ty::{
self, suggest_arbitrary_trait_bound, suggest_constraining_type_param, AdtKind, GenericArgs,
@ -3842,7 +3842,7 @@ fn note_function_argument_obligation<G: EmissionGuarantee>(
&& let Some(failed_pred) = failed_pred.as_projection_clause()
&& let Some(found) = failed_pred.skip_binder().term.as_type()
{
type_diffs = vec![Sorts(ty::error::ExpectedFound {
type_diffs = vec![TypeError::Sorts(ty::error::ExpectedFound {
expected: where_pred
.skip_binder()
.projection_term
@ -3985,7 +3985,7 @@ fn look_for_iterator_item_mistakes<G: EmissionGuarantee>(
continue;
};
for diff in type_diffs {
let Sorts(expected_found) = diff else {
let TypeError::Sorts(expected_found) = diff else {
continue;
};
if tcx.is_diagnostic_item(sym::IteratorItem, *def_id)
@ -4165,7 +4165,7 @@ fn point_at_chain<G: EmissionGuarantee>(
};
if primary_spans.is_empty()
|| type_diffs.iter().any(|diff| {
let Sorts(expected_found) = diff else {
let TypeError::Sorts(expected_found) = diff else {
return false;
};
self.can_eq(param_env, expected_found.found, ty)
@ -4198,7 +4198,7 @@ fn point_at_chain<G: EmissionGuarantee>(
let assoc = with_forced_trimmed_paths!(self.tcx.def_path_str(assoc));
if !self.can_eq(param_env, ty, *prev_ty) {
if type_diffs.iter().any(|diff| {
let Sorts(expected_found) = diff else {
let TypeError::Sorts(expected_found) = diff else {
return false;
};
self.can_eq(param_env, expected_found.found, ty)
@ -4248,7 +4248,7 @@ fn probe_assoc_types_at_expr(
let ocx = ObligationCtxt::new(self.infcx);
let mut assocs_in_this_method = Vec::with_capacity(type_diffs.len());
for diff in type_diffs {
let Sorts(expected_found) = diff else {
let TypeError::Sorts(expected_found) = diff else {
continue;
};
let ty::Alias(ty::Projection, proj) = expected_found.expected.kind() else {

View file

@ -32,6 +32,8 @@
use rustc_errors::{Diag, EmissionGuarantee};
use rustc_hir as hir;
use rustc_hir::def_id::DefId;
use rustc_infer::infer::relate::MatchAgainstFreshVars;
use rustc_infer::infer::relate::TypeRelation;
use rustc_infer::infer::BoundRegionConversionTime;
use rustc_infer::infer::BoundRegionConversionTime::HigherRankedType;
use rustc_infer::infer::DefineOpaqueTypes;
@ -40,10 +42,9 @@
use rustc_middle::dep_graph::dep_kinds;
use rustc_middle::dep_graph::DepNodeIndex;
use rustc_middle::mir::interpret::ErrorHandled;
use rustc_middle::ty::_match::MatchAgainstFreshVars;
use rustc_middle::ty::abstract_const::NotConstEvaluatable;
use rustc_middle::ty::error::TypeErrorToStringExt;
use rustc_middle::ty::print::PrintTraitRefExt as _;
use rustc_middle::ty::relate::TypeRelation;
use rustc_middle::ty::GenericArgsRef;
use rustc_middle::ty::{self, PolyProjectionPredicate, Upcast};
use rustc_middle::ty::{Ty, TyCtxt, TypeFoldable, TypeVisitableExt};

View file

@ -0,0 +1,106 @@
use rustc_type_ir_macros::{TypeFoldable_Generic, TypeVisitable_Generic};
use crate::solve::NoSolution;
use crate::{self as ty, Interner};
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
#[derive(TypeFoldable_Generic, TypeVisitable_Generic)]
pub struct ExpectedFound<T> {
pub expected: T,
pub found: T,
}
impl<T> ExpectedFound<T> {
pub fn new(a_is_expected: bool, a: T, b: T) -> Self {
if a_is_expected {
ExpectedFound { expected: a, found: b }
} else {
ExpectedFound { expected: b, found: a }
}
}
}
// Data structures used in type unification
#[derive(derivative::Derivative)]
#[derivative(
Clone(bound = ""),
Copy(bound = ""),
PartialEq(bound = ""),
Eq(bound = ""),
Debug(bound = "")
)]
#[derive(TypeVisitable_Generic)]
#[rustc_pass_by_value]
pub enum TypeError<I: Interner> {
Mismatch,
ConstnessMismatch(ExpectedFound<ty::BoundConstness>),
PolarityMismatch(ExpectedFound<ty::PredicatePolarity>),
SafetyMismatch(ExpectedFound<I::Safety>),
AbiMismatch(ExpectedFound<I::Abi>),
Mutability,
ArgumentMutability(usize),
TupleSize(ExpectedFound<usize>),
FixedArraySize(ExpectedFound<u64>),
ArgCount,
RegionsDoesNotOutlive(I::Region, I::Region),
RegionsInsufficientlyPolymorphic(I::BoundRegion, I::Region),
RegionsPlaceholderMismatch,
Sorts(ExpectedFound<I::Ty>),
ArgumentSorts(ExpectedFound<I::Ty>, usize),
Traits(ExpectedFound<I::DefId>),
VariadicMismatch(ExpectedFound<bool>),
/// Instantiating a type variable with the given type would have
/// created a cycle (because it appears somewhere within that
/// type).
CyclicTy(I::Ty),
CyclicConst(I::Const),
ProjectionMismatched(ExpectedFound<I::DefId>),
ExistentialMismatch(ExpectedFound<I::BoundExistentialPredicates>),
ConstMismatch(ExpectedFound<I::Const>),
IntrinsicCast,
/// Safe `#[target_feature]` functions are not assignable to safe function pointers.
TargetFeatureCast(I::DefId),
}
impl<I: Interner> TypeError<I> {
pub fn involves_regions(self) -> bool {
match self {
TypeError::RegionsDoesNotOutlive(_, _)
| TypeError::RegionsInsufficientlyPolymorphic(_, _)
| TypeError::RegionsPlaceholderMismatch => true,
_ => false,
}
}
pub fn must_include_note(self) -> bool {
use self::TypeError::*;
match self {
CyclicTy(_) | CyclicConst(_) | SafetyMismatch(_) | ConstnessMismatch(_)
| PolarityMismatch(_) | Mismatch | AbiMismatch(_) | FixedArraySize(_)
| ArgumentSorts(..) | Sorts(_) | VariadicMismatch(_) | TargetFeatureCast(_) => false,
Mutability
| ArgumentMutability(_)
| TupleSize(_)
| ArgCount
| RegionsDoesNotOutlive(..)
| RegionsInsufficientlyPolymorphic(..)
| RegionsPlaceholderMismatch
| Traits(_)
| ProjectionMismatched(_)
| ExistentialMismatch(_)
| ConstMismatch(_)
| IntrinsicCast => true,
}
}
}
impl<I: Interner> From<TypeError<I>> for NoSolution {
fn from(_: TypeError<I>) -> NoSolution {
NoSolution
}
}

View file

@ -7,7 +7,10 @@
use std::hash::Hash;
use std::ops::Deref;
use rustc_ast_ir::Mutability;
use crate::fold::{TypeFoldable, TypeSuperFoldable};
use crate::relate::Relate;
use crate::visit::{Flags, TypeSuperVisitable, TypeVisitable};
use crate::{self as ty, CollectAndApply, DebugWithInfcx, Interner, UpcastFrom};
@ -21,6 +24,7 @@ pub trait Ty<I: Interner<Ty = Self>>:
+ IntoKind<Kind = ty::TyKind<I>>
+ TypeSuperVisitable<I>
+ TypeSuperFoldable<I>
+ Relate<I>
+ Flags
{
fn new_bool(interner: I) -> Self;
@ -35,8 +39,37 @@ pub trait Ty<I: Interner<Ty = Self>>:
fn new_alias(interner: I, kind: ty::AliasTyKind, alias_ty: ty::AliasTy<I>) -> Self;
fn new_error(interner: I, guar: I::ErrorGuaranteed) -> Self;
fn new_adt(interner: I, adt_def: I::AdtDef, args: I::GenericArgs) -> Self;
fn new_foreign(interner: I, def_id: I::DefId) -> Self;
fn new_dynamic(
interner: I,
preds: I::BoundExistentialPredicates,
region: I::Region,
kind: ty::DynKind,
) -> Self;
fn new_coroutine(interner: I, def_id: I::DefId, args: I::GenericArgs) -> Self;
fn new_coroutine_closure(interner: I, def_id: I::DefId, args: I::GenericArgs) -> Self;
fn new_closure(interner: I, def_id: I::DefId, args: I::GenericArgs) -> Self;
fn new_coroutine_witness(interner: I, def_id: I::DefId, args: I::GenericArgs) -> Self;
fn new_ptr(interner: I, ty: Self, mutbl: Mutability) -> Self;
fn new_ref(interner: I, region: I::Region, ty: Self, mutbl: Mutability) -> Self;
fn new_array_with_const_len(interner: I, ty: Self, len: I::Const) -> Self;
fn new_slice(interner: I, ty: Self) -> Self;
fn new_tup(interner: I, tys: &[I::Ty]) -> Self;
fn new_tup_from_iter<It, T>(interner: I, iter: It) -> T::Output
where
It: Iterator<Item = T>,
@ -49,6 +82,12 @@ fn new_tup_from_iter<It, T>(interner: I, iter: It) -> T::Output
fn from_closure_kind(interner: I, kind: ty::ClosureKind) -> Self;
fn from_coroutine_closure_kind(interner: I, kind: ty::ClosureKind) -> Self;
fn new_fn_def(interner: I, def_id: I::DefId, args: I::GenericArgs) -> Self;
fn new_fn_ptr(interner: I, sig: ty::Binder<I, ty::FnSig<I>>) -> Self;
fn new_pat(interner: I, ty: Self, pat: I::Pat) -> Self;
}
pub trait Tys<I: Interner<Tys = Self>>:
@ -84,6 +123,7 @@ pub trait Region<I: Interner<Region = Self>>:
+ IntoKind<Kind = ty::RegionKind<I>>
+ Flags
+ TypeVisitable<I>
+ Relate<I>
{
fn new_bound(interner: I, debruijn: ty::DebruijnIndex, var: I::BoundRegion) -> Self;
@ -102,8 +142,11 @@ pub trait Const<I: Interner<Const = Self>>:
+ IntoKind<Kind = ty::ConstKind<I>>
+ TypeSuperVisitable<I>
+ TypeSuperFoldable<I>
+ Relate<I>
+ Flags
{
fn try_to_target_usize(self, interner: I) -> Option<u64>;
fn new_infer(interner: I, var: ty::InferConst) -> Self;
fn new_var(interner: I, var: ty::ConstVid) -> Self;
@ -113,6 +156,8 @@ pub trait Const<I: Interner<Const = Self>>:
fn new_anon_bound(interner: I, debruijn: ty::DebruijnIndex, var: ty::BoundVar) -> Self;
fn new_unevaluated(interner: I, uv: ty::UnevaluatedConst<I>) -> Self;
fn new_expr(interner: I, expr: I::ExprConst) -> Self;
}
pub trait GenericsOf<I: Interner<GenericsOf = Self>> {
@ -128,13 +173,14 @@ pub trait GenericArgs<I: Interner<GenericArgs = Self>>:
+ Deref<Target: Deref<Target = [I::GenericArg]>>
+ Default
+ TypeFoldable<I>
+ Relate<I>
{
fn type_at(self, i: usize) -> I::Ty;
fn identity_for_item(interner: I, def_id: I::DefId) -> I::GenericArgs;
fn extend_with_error(
tcx: I,
interner: I,
def_id: I::DefId,
original_args: &[I::GenericArg],
) -> I::GenericArgs;
@ -193,3 +239,11 @@ pub trait BoundVarLike<I: Interner> {
pub trait ParamLike {
fn index(self) -> u32;
}
pub trait AdtDef<I: Interner>: Copy + Debug + Hash + Eq {
fn def_id(self) -> I::DefId;
}
pub trait Features<I: Interner>: Copy {
fn generic_const_exprs(self) -> bool;
}

View file

@ -6,6 +6,7 @@
use crate::fold::TypeFoldable;
use crate::inherent::*;
use crate::ir_print::IrPrint;
use crate::relate::Relate;
use crate::solve::inspect::CanonicalGoalEvaluationStep;
use crate::visit::{Flags, TypeSuperVisitable, TypeVisitable};
use crate::{self as ty, DebugWithInfcx};
@ -25,8 +26,8 @@ pub trait Interner:
+ IrPrint<ty::CoercePredicate<Self>>
+ IrPrint<ty::FnSig<Self>>
{
type DefId: Copy + Debug + Hash + Eq + TypeVisitable<Self>;
type AdtDef: Copy + Debug + Hash + Eq;
type DefId: Copy + Debug + Hash + Eq + TypeFoldable<Self>;
type AdtDef: AdtDef<Self>;
type GenericArgs: GenericArgs<Self>;
type GenericArgsSlice: Copy + Debug + Hash + Eq + Deref<Target = [Self::GenericArg]>;
@ -35,8 +36,15 @@ pub trait Interner:
+ Hash
+ Eq
+ IntoKind<Kind = ty::GenericArgKind<Self>>
+ TypeVisitable<Self>;
type Term: Copy + Debug + Hash + Eq + IntoKind<Kind = ty::TermKind<Self>> + TypeVisitable<Self>;
+ TypeVisitable<Self>
+ Relate<Self>;
type Term: Copy
+ Debug
+ Hash
+ Eq
+ IntoKind<Kind = ty::TermKind<Self>>
+ TypeFoldable<Self>
+ Relate<Self>;
type BoundVarKinds: Copy
+ Debug
@ -66,11 +74,11 @@ pub trait Interner:
// Things stored inside of tys
type ErrorGuaranteed: Copy + Debug + Hash + Eq;
type BoundExistentialPredicates: Copy + DebugWithInfcx<Self> + Hash + Eq;
type BoundExistentialPredicates: Copy + DebugWithInfcx<Self> + Hash + Eq + Relate<Self>;
type AllocId: Copy + Debug + Hash + Eq;
type Pat: Copy + Debug + Hash + Eq + DebugWithInfcx<Self>;
type Safety: Safety<Self>;
type Abi: Abi<Self>;
type Pat: Copy + Debug + Hash + Eq + DebugWithInfcx<Self> + Relate<Self>;
type Safety: Safety<Self> + TypeFoldable<Self> + Relate<Self>;
type Abi: Abi<Self> + TypeFoldable<Self> + Relate<Self>;
// Kinds of consts
type Const: Const<Self>;
@ -78,7 +86,7 @@ pub trait Interner:
type ParamConst: Copy + Debug + Hash + Eq + ParamLike;
type BoundConst: Copy + Debug + Hash + Eq + BoundVarLike<Self>;
type ValueConst: Copy + Debug + Hash + Eq;
type ExprConst: Copy + DebugWithInfcx<Self> + Hash + Eq;
type ExprConst: Copy + DebugWithInfcx<Self> + Hash + Eq + Relate<Self>;
// Kinds of regions
type Region: Region<Self>;
@ -93,11 +101,16 @@ pub trait Interner:
type Clause: Clause<Self>;
type Clauses: Copy + Debug + Hash + Eq + TypeSuperVisitable<Self> + Flags;
fn expand_abstract_consts<T: TypeFoldable<Self>>(self, t: T) -> T;
fn mk_canonical_var_infos(self, infos: &[ty::CanonicalVarInfo<Self>]) -> Self::CanonicalVars;
type GenericsOf: GenericsOf<Self>;
fn generics_of(self, def_id: Self::DefId) -> Self::GenericsOf;
type VariancesOf: Copy + Debug + Deref<Target = [ty::Variance]>;
fn variances_of(self, def_id: Self::DefId) -> Self::VariancesOf;
// FIXME: Remove after uplifting `EarlyBinder`
fn type_of(self, def_id: Self::DefId) -> ty::EarlyBinder<Self, Self::Ty>;
@ -112,7 +125,12 @@ fn trait_ref_and_own_args_for_alias(
) -> (ty::TraitRef<Self>, Self::GenericArgsSlice);
fn mk_args(self, args: &[Self::GenericArg]) -> Self::GenericArgs;
fn mk_args_from_iter(self, args: impl Iterator<Item = Self::GenericArg>) -> Self::GenericArgs;
fn mk_args_from_iter<I, T>(self, args: I) -> T::Output
where
I: Iterator<Item = T>,
T: CollectAndApply<Self::GenericArg, Self::GenericArgs>;
fn check_and_mk_args(
self,
def_id: Self::DefId,
@ -124,9 +142,17 @@ fn intern_canonical_goal_evaluation_step(
step: CanonicalGoalEvaluationStep<Self>,
) -> Self::CanonicalGoalEvaluationStepRef;
fn mk_type_list_from_iter<I, T>(self, args: I) -> T::Output
where
I: Iterator<Item = T>,
T: CollectAndApply<Self::Ty, Self::Tys>;
fn parent(self, def_id: Self::DefId) -> Self::DefId;
fn recursion_limit(self) -> usize;
type Features: Features<Self>;
fn features(self) -> Self::Features;
}
/// Imagine you have a function `F: FnOnce(&[T]) -> R`, plus an iterator `iter`

View file

@ -21,18 +21,20 @@
#[cfg(not(feature = "nightly"))]
use std::sync::Arc as Lrc;
// These modules are `pub` since they are not glob-imported.
#[macro_use]
pub mod visit;
#[cfg(feature = "nightly")]
pub mod codec;
pub mod error;
pub mod fold;
pub mod inherent;
pub mod ir_print;
pub mod lift;
pub mod relate;
pub mod solve;
pub mod ty_info;
pub mod ty_kind;
// These modules are not `pub` since they are glob-imported.
#[macro_use]
mod macros;
mod binder;
@ -46,6 +48,8 @@
mod predicate;
mod predicate_kind;
mod region_kind;
mod ty_info;
mod ty_kind;
mod upcast;
pub use binder::*;

View file

@ -48,10 +48,22 @@ fn visit_with<F: $crate::visit::TypeVisitor<I>>(
u32,
u64,
String,
crate::DebruijnIndex,
crate::AliasRelationDirection,
crate::UniverseIndex,
rustc_ast_ir::Mutability,
rustc_ast_ir::Movability,
crate::AliasTyKind,
crate::BoundConstness,
crate::DebruijnIndex,
crate::FloatTy,
crate::InferTy,
crate::IntVarValue,
crate::PredicatePolarity,
crate::RegionVid,
crate::solve::BuiltinImplSource,
crate::solve::Certainty,
crate::solve::GoalSource,
crate::solve::MaybeCause,
crate::solve::NoSolution,
crate::UniverseIndex,
crate::Variance,
rustc_ast_ir::Movability,
rustc_ast_ir::Mutability,
}

View file

@ -793,3 +793,36 @@ pub struct CoercePredicate<I: Interner> {
pub a: I::Ty,
pub b: I::Ty,
}
#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)]
#[cfg_attr(feature = "nightly", derive(HashStable_NoContext, TyEncodable, TyDecodable))]
pub enum BoundConstness {
/// `Type: Trait`
NotConst,
/// `Type: const Trait`
Const,
/// `Type: ~const Trait`
///
/// Requires resolving to const only when we are in a const context.
ConstIfConst,
}
impl BoundConstness {
pub fn as_str(self) -> &'static str {
match self {
Self::NotConst => "",
Self::Const => "const",
Self::ConstIfConst => "~const",
}
}
}
impl fmt::Display for BoundConstness {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
Self::NotConst => f.write_str("normal"),
Self::Const => f.write_str("const"),
Self::ConstIfConst => f.write_str("~const"),
}
}
}

View file

@ -0,0 +1,666 @@
use std::iter;
use rustc_ast_ir::Mutability;
use rustc_type_ir::error::{ExpectedFound, TypeError};
use rustc_type_ir::fold::TypeFoldable;
use rustc_type_ir::inherent::*;
use rustc_type_ir::{self as ty, Interner};
use tracing::{debug, instrument};
pub type RelateResult<I, T> = Result<T, TypeError<I>>;
/// Extra information about why we ended up with a particular variance.
/// This is only used to add more information to error messages, and
/// has no effect on soundness. While choosing the 'wrong' `VarianceDiagInfo`
/// may lead to confusing notes in error messages, it will never cause
/// a miscompilation or unsoundness.
///
/// When in doubt, use `VarianceDiagInfo::default()`
#[derive(derivative::Derivative)]
#[derivative(
Copy(bound = ""),
Clone(bound = ""),
Debug(bound = ""),
Default(bound = ""),
PartialEq(bound = ""),
Eq(bound = "")
)]
pub enum VarianceDiagInfo<I: Interner> {
/// No additional information - this is the default.
/// We will not add any additional information to error messages.
#[derivative(Default)]
None,
/// We switched our variance because a generic argument occurs inside
/// the invariant generic argument of another type.
Invariant {
/// The generic type containing the generic parameter
/// that changes the variance (e.g. `*mut T`, `MyStruct<T>`)
ty: I::Ty,
/// The index of the generic parameter being used
/// (e.g. `0` for `*mut T`, `1` for `MyStruct<'CovariantParam, 'InvariantParam>`)
param_index: u32,
},
}
impl<I: Interner> VarianceDiagInfo<I> {
/// Mirrors `Variance::xform` - used to 'combine' the existing
/// and new `VarianceDiagInfo`s when our variance changes.
pub fn xform(self, other: VarianceDiagInfo<I>) -> VarianceDiagInfo<I> {
// For now, just use the first `VarianceDiagInfo::Invariant` that we see
match self {
VarianceDiagInfo::None => other,
VarianceDiagInfo::Invariant { .. } => self,
}
}
}
pub trait TypeRelation<I: Interner>: Sized {
fn tcx(&self) -> I;
/// Returns a static string we can use for printouts.
fn tag(&self) -> &'static str;
/// Generic relation routine suitable for most anything.
fn relate<T: Relate<I>>(&mut self, a: T, b: T) -> RelateResult<I, T> {
Relate::relate(self, a, b)
}
/// Relate the two args for the given item. The default
/// is to look up the variance for the item and proceed
/// accordingly.
fn relate_item_args(
&mut self,
item_def_id: I::DefId,
a_arg: I::GenericArgs,
b_arg: I::GenericArgs,
) -> RelateResult<I, I::GenericArgs> {
debug!(
"relate_item_args(item_def_id={:?}, a_arg={:?}, b_arg={:?})",
item_def_id, a_arg, b_arg
);
let tcx = self.tcx();
let opt_variances = tcx.variances_of(item_def_id);
relate_args_with_variances(self, item_def_id, &opt_variances, a_arg, b_arg, true)
}
/// Switch variance for the purpose of relating `a` and `b`.
fn relate_with_variance<T: Relate<I>>(
&mut self,
variance: ty::Variance,
info: VarianceDiagInfo<I>,
a: T,
b: T,
) -> RelateResult<I, T>;
// Overridable relations. You shouldn't typically call these
// directly, instead call `relate()`, which in turn calls
// these. This is both more uniform but also allows us to add
// additional hooks for other types in the future if needed
// without making older code, which called `relate`, obsolete.
fn tys(&mut self, a: I::Ty, b: I::Ty) -> RelateResult<I, I::Ty>;
fn regions(&mut self, a: I::Region, b: I::Region) -> RelateResult<I, I::Region>;
fn consts(&mut self, a: I::Const, b: I::Const) -> RelateResult<I, I::Const>;
fn binders<T>(
&mut self,
a: ty::Binder<I, T>,
b: ty::Binder<I, T>,
) -> RelateResult<I, ty::Binder<I, T>>
where
T: Relate<I>;
}
pub trait Relate<I: Interner>: TypeFoldable<I> + PartialEq + Copy {
fn relate<R: TypeRelation<I>>(relation: &mut R, a: Self, b: Self) -> RelateResult<I, Self>;
}
///////////////////////////////////////////////////////////////////////////
// Relate impls
#[inline]
pub fn relate_args_invariantly<I: Interner, R: TypeRelation<I>>(
relation: &mut R,
a_arg: I::GenericArgs,
b_arg: I::GenericArgs,
) -> RelateResult<I, I::GenericArgs> {
relation.tcx().mk_args_from_iter(iter::zip(a_arg, b_arg).map(|(a, b)| {
relation.relate_with_variance(ty::Variance::Invariant, VarianceDiagInfo::default(), a, b)
}))
}
pub fn relate_args_with_variances<I: Interner, R: TypeRelation<I>>(
relation: &mut R,
ty_def_id: I::DefId,
variances: &[ty::Variance],
a_arg: I::GenericArgs,
b_arg: I::GenericArgs,
fetch_ty_for_diag: bool,
) -> RelateResult<I, I::GenericArgs> {
let tcx = relation.tcx();
let mut cached_ty = None;
let params = iter::zip(a_arg, b_arg).enumerate().map(|(i, (a, b))| {
let variance = variances[i];
let variance_info = if variance == ty::Variance::Invariant && fetch_ty_for_diag {
let ty =
*cached_ty.get_or_insert_with(|| tcx.type_of(ty_def_id).instantiate(tcx, &a_arg));
VarianceDiagInfo::Invariant { ty, param_index: i.try_into().unwrap() }
} else {
VarianceDiagInfo::default()
};
relation.relate_with_variance(variance, variance_info, a, b)
});
tcx.mk_args_from_iter(params)
}
impl<I: Interner> Relate<I> for ty::FnSig<I> {
fn relate<R: TypeRelation<I>>(
relation: &mut R,
a: ty::FnSig<I>,
b: ty::FnSig<I>,
) -> RelateResult<I, ty::FnSig<I>> {
let tcx = relation.tcx();
if a.c_variadic != b.c_variadic {
return Err(TypeError::VariadicMismatch({
let a = a.c_variadic;
let b = b.c_variadic;
ExpectedFound::new(true, a, b)
}));
}
let safety = relation.relate(a.safety, b.safety)?;
let abi = relation.relate(a.abi, b.abi)?;
let a_inputs = a.inputs();
let b_inputs = b.inputs();
if a_inputs.len() != b_inputs.len() {
return Err(TypeError::ArgCount);
}
let inputs_and_output = iter::zip(a_inputs.iter(), b_inputs.iter())
.map(|(&a, &b)| ((a, b), false))
.chain(iter::once(((a.output(), b.output()), true)))
.map(|((a, b), is_output)| {
if is_output {
relation.relate(a, b)
} else {
relation.relate_with_variance(
ty::Variance::Contravariant,
VarianceDiagInfo::default(),
a,
b,
)
}
})
.enumerate()
.map(|(i, r)| match r {
Err(TypeError::Sorts(exp_found) | TypeError::ArgumentSorts(exp_found, _)) => {
Err(TypeError::ArgumentSorts(exp_found, i))
}
Err(TypeError::Mutability | TypeError::ArgumentMutability(_)) => {
Err(TypeError::ArgumentMutability(i))
}
r => r,
});
Ok(ty::FnSig {
inputs_and_output: tcx.mk_type_list_from_iter(inputs_and_output)?,
c_variadic: a.c_variadic,
safety,
abi,
})
}
}
impl<I: Interner> Relate<I> for ty::BoundConstness {
fn relate<R: TypeRelation<I>>(
_relation: &mut R,
a: ty::BoundConstness,
b: ty::BoundConstness,
) -> RelateResult<I, ty::BoundConstness> {
if a != b {
Err(TypeError::ConstnessMismatch(ExpectedFound::new(true, a, b)))
} else {
Ok(a)
}
}
}
impl<I: Interner> Relate<I> for ty::AliasTy<I> {
fn relate<R: TypeRelation<I>>(
relation: &mut R,
a: ty::AliasTy<I>,
b: ty::AliasTy<I>,
) -> RelateResult<I, ty::AliasTy<I>> {
if a.def_id != b.def_id {
Err(TypeError::ProjectionMismatched({
let a = a.def_id;
let b = b.def_id;
ExpectedFound::new(true, a, b)
}))
} else {
let args = match a.kind(relation.tcx()) {
ty::Opaque => relate_args_with_variances(
relation,
a.def_id,
&relation.tcx().variances_of(a.def_id),
a.args,
b.args,
false, // do not fetch `type_of(a_def_id)`, as it will cause a cycle
)?,
ty::Projection | ty::Weak | ty::Inherent => {
relate_args_invariantly(relation, a.args, b.args)?
}
};
Ok(ty::AliasTy::new(relation.tcx(), a.def_id, args))
}
}
}
impl<I: Interner> Relate<I> for ty::AliasTerm<I> {
fn relate<R: TypeRelation<I>>(
relation: &mut R,
a: ty::AliasTerm<I>,
b: ty::AliasTerm<I>,
) -> RelateResult<I, ty::AliasTerm<I>> {
if a.def_id != b.def_id {
Err(TypeError::ProjectionMismatched({
let a = a.def_id;
let b = b.def_id;
ExpectedFound::new(true, a, b)
}))
} else {
let args = match a.kind(relation.tcx()) {
ty::AliasTermKind::OpaqueTy => relate_args_with_variances(
relation,
a.def_id,
&relation.tcx().variances_of(a.def_id),
a.args,
b.args,
false, // do not fetch `type_of(a_def_id)`, as it will cause a cycle
)?,
ty::AliasTermKind::ProjectionTy
| ty::AliasTermKind::WeakTy
| ty::AliasTermKind::InherentTy
| ty::AliasTermKind::UnevaluatedConst
| ty::AliasTermKind::ProjectionConst => {
relate_args_invariantly(relation, a.args, b.args)?
}
};
Ok(ty::AliasTerm::new(relation.tcx(), a.def_id, args))
}
}
}
impl<I: Interner> Relate<I> for ty::ExistentialProjection<I> {
fn relate<R: TypeRelation<I>>(
relation: &mut R,
a: ty::ExistentialProjection<I>,
b: ty::ExistentialProjection<I>,
) -> RelateResult<I, ty::ExistentialProjection<I>> {
if a.def_id != b.def_id {
Err(TypeError::ProjectionMismatched({
let a = a.def_id;
let b = b.def_id;
ExpectedFound::new(true, a, b)
}))
} else {
let term = relation.relate_with_variance(
ty::Variance::Invariant,
VarianceDiagInfo::default(),
a.term,
b.term,
)?;
let args = relation.relate_with_variance(
ty::Variance::Invariant,
VarianceDiagInfo::default(),
a.args,
b.args,
)?;
Ok(ty::ExistentialProjection { def_id: a.def_id, args, term })
}
}
}
impl<I: Interner> Relate<I> for ty::TraitRef<I> {
fn relate<R: TypeRelation<I>>(
relation: &mut R,
a: ty::TraitRef<I>,
b: ty::TraitRef<I>,
) -> RelateResult<I, ty::TraitRef<I>> {
// Different traits cannot be related.
if a.def_id != b.def_id {
Err(TypeError::Traits({
let a = a.def_id;
let b = b.def_id;
ExpectedFound::new(true, a, b)
}))
} else {
let args = relate_args_invariantly(relation, a.args, b.args)?;
Ok(ty::TraitRef::new(relation.tcx(), a.def_id, args))
}
}
}
impl<I: Interner> Relate<I> for ty::ExistentialTraitRef<I> {
fn relate<R: TypeRelation<I>>(
relation: &mut R,
a: ty::ExistentialTraitRef<I>,
b: ty::ExistentialTraitRef<I>,
) -> RelateResult<I, ty::ExistentialTraitRef<I>> {
// Different traits cannot be related.
if a.def_id != b.def_id {
Err(TypeError::Traits({
let a = a.def_id;
let b = b.def_id;
ExpectedFound::new(true, a, b)
}))
} else {
let args = relate_args_invariantly(relation, a.args, b.args)?;
Ok(ty::ExistentialTraitRef { def_id: a.def_id, args })
}
}
}
/// Relates `a` and `b` structurally, calling the relation for all nested values.
/// Any semantic equality, e.g. of projections, and inference variables have to be
/// handled by the caller.
#[instrument(level = "trace", skip(relation), ret)]
pub fn structurally_relate_tys<I: Interner, R: TypeRelation<I>>(
relation: &mut R,
a: I::Ty,
b: I::Ty,
) -> RelateResult<I, I::Ty> {
let tcx = relation.tcx();
match (a.kind(), b.kind()) {
(ty::Infer(_), _) | (_, ty::Infer(_)) => {
// The caller should handle these cases!
panic!("var types encountered in structurally_relate_tys")
}
(ty::Bound(..), _) | (_, ty::Bound(..)) => {
panic!("bound types encountered in structurally_relate_tys")
}
(ty::Error(guar), _) | (_, ty::Error(guar)) => Ok(Ty::new_error(tcx, guar)),
(ty::Never, _)
| (ty::Char, _)
| (ty::Bool, _)
| (ty::Int(_), _)
| (ty::Uint(_), _)
| (ty::Float(_), _)
| (ty::Str, _)
if a == b =>
{
Ok(a)
}
(ty::Param(a_p), ty::Param(b_p)) if a_p.index() == b_p.index() => {
// FIXME: Put this back
//debug_assert_eq!(a_p.name(), b_p.name(), "param types with same index differ in name");
Ok(a)
}
(ty::Placeholder(p1), ty::Placeholder(p2)) if p1 == p2 => Ok(a),
(ty::Adt(a_def, a_args), ty::Adt(b_def, b_args)) if a_def == b_def => {
let args = relation.relate_item_args(a_def.def_id(), a_args, b_args)?;
Ok(Ty::new_adt(tcx, a_def, args))
}
(ty::Foreign(a_id), ty::Foreign(b_id)) if a_id == b_id => Ok(Ty::new_foreign(tcx, a_id)),
(ty::Dynamic(a_obj, a_region, a_repr), ty::Dynamic(b_obj, b_region, b_repr))
if a_repr == b_repr =>
{
Ok(Ty::new_dynamic(
tcx,
relation.relate(a_obj, b_obj)?,
relation.relate(a_region, b_region)?,
a_repr,
))
}
(ty::Coroutine(a_id, a_args), ty::Coroutine(b_id, b_args)) if a_id == b_id => {
// All Coroutine types with the same id represent
// the (anonymous) type of the same coroutine expression. So
// all of their regions should be equated.
let args = relate_args_invariantly(relation, a_args, b_args)?;
Ok(Ty::new_coroutine(tcx, a_id, args))
}
(ty::CoroutineWitness(a_id, a_args), ty::CoroutineWitness(b_id, b_args))
if a_id == b_id =>
{
// All CoroutineWitness types with the same id represent
// the (anonymous) type of the same coroutine expression. So
// all of their regions should be equated.
let args = relate_args_invariantly(relation, a_args, b_args)?;
Ok(Ty::new_coroutine_witness(tcx, a_id, args))
}
(ty::Closure(a_id, a_args), ty::Closure(b_id, b_args)) if a_id == b_id => {
// All Closure types with the same id represent
// the (anonymous) type of the same closure expression. So
// all of their regions should be equated.
let args = relate_args_invariantly(relation, a_args, b_args)?;
Ok(Ty::new_closure(tcx, a_id, args))
}
(ty::CoroutineClosure(a_id, a_args), ty::CoroutineClosure(b_id, b_args))
if a_id == b_id =>
{
let args = relate_args_invariantly(relation, a_args, b_args)?;
Ok(Ty::new_coroutine_closure(tcx, a_id, args))
}
(ty::RawPtr(a_ty, a_mutbl), ty::RawPtr(b_ty, b_mutbl)) => {
if a_mutbl != b_mutbl {
return Err(TypeError::Mutability);
}
let (variance, info) = match a_mutbl {
Mutability::Not => (ty::Variance::Covariant, VarianceDiagInfo::None),
Mutability::Mut => {
(ty::Variance::Invariant, VarianceDiagInfo::Invariant { ty: a, param_index: 0 })
}
};
let ty = relation.relate_with_variance(variance, info, a_ty, b_ty)?;
Ok(Ty::new_ptr(tcx, ty, a_mutbl))
}
(ty::Ref(a_r, a_ty, a_mutbl), ty::Ref(b_r, b_ty, b_mutbl)) => {
if a_mutbl != b_mutbl {
return Err(TypeError::Mutability);
}
let (variance, info) = match a_mutbl {
Mutability::Not => (ty::Variance::Covariant, VarianceDiagInfo::None),
Mutability::Mut => {
(ty::Variance::Invariant, VarianceDiagInfo::Invariant { ty: a, param_index: 0 })
}
};
let r = relation.relate(a_r, b_r)?;
let ty = relation.relate_with_variance(variance, info, a_ty, b_ty)?;
Ok(Ty::new_ref(tcx, r, ty, a_mutbl))
}
(ty::Array(a_t, sz_a), ty::Array(b_t, sz_b)) => {
let t = relation.relate(a_t, b_t)?;
match relation.relate(sz_a, sz_b) {
Ok(sz) => Ok(Ty::new_array_with_const_len(tcx, t, sz)),
Err(err) => {
// Check whether the lengths are both concrete/known values,
// but are unequal, for better diagnostics.
let sz_a = sz_a.try_to_target_usize(tcx);
let sz_b = sz_b.try_to_target_usize(tcx);
match (sz_a, sz_b) {
(Some(sz_a_val), Some(sz_b_val)) if sz_a_val != sz_b_val => Err(
TypeError::FixedArraySize(ExpectedFound::new(true, sz_a_val, sz_b_val)),
),
_ => Err(err),
}
}
}
}
(ty::Slice(a_t), ty::Slice(b_t)) => {
let t = relation.relate(a_t, b_t)?;
Ok(Ty::new_slice(tcx, t))
}
(ty::Tuple(as_), ty::Tuple(bs)) => {
if as_.len() == bs.len() {
Ok(Ty::new_tup_from_iter(
tcx,
iter::zip(as_, bs).map(|(a, b)| relation.relate(a, b)),
)?)
} else if !(as_.is_empty() || bs.is_empty()) {
Err(TypeError::TupleSize(ExpectedFound::new(true, as_.len(), bs.len())))
} else {
Err(TypeError::Sorts(ExpectedFound::new(true, a, b)))
}
}
(ty::FnDef(a_def_id, a_args), ty::FnDef(b_def_id, b_args)) if a_def_id == b_def_id => {
let args = relation.relate_item_args(a_def_id, a_args, b_args)?;
Ok(Ty::new_fn_def(tcx, a_def_id, args))
}
(ty::FnPtr(a_fty), ty::FnPtr(b_fty)) => {
let fty = relation.relate(a_fty, b_fty)?;
Ok(Ty::new_fn_ptr(tcx, fty))
}
// Alias tend to mostly already be handled downstream due to normalization.
(ty::Alias(a_kind, a_data), ty::Alias(b_kind, b_data)) => {
let alias_ty = relation.relate(a_data, b_data)?;
assert_eq!(a_kind, b_kind);
Ok(Ty::new_alias(tcx, a_kind, alias_ty))
}
(ty::Pat(a_ty, a_pat), ty::Pat(b_ty, b_pat)) => {
let ty = relation.relate(a_ty, b_ty)?;
let pat = relation.relate(a_pat, b_pat)?;
Ok(Ty::new_pat(tcx, ty, pat))
}
_ => Err(TypeError::Sorts(ExpectedFound::new(true, a, b))),
}
}
/// Relates `a` and `b` structurally, calling the relation for all nested values.
/// Any semantic equality, e.g. of unevaluated consts, and inference variables have
/// to be handled by the caller.
///
/// FIXME: This is not totally structual, which probably should be fixed.
/// See the HACKs below.
pub fn structurally_relate_consts<I: Interner, R: TypeRelation<I>>(
relation: &mut R,
mut a: I::Const,
mut b: I::Const,
) -> RelateResult<I, I::Const> {
debug!("{}.structurally_relate_consts(a = {:?}, b = {:?})", relation.tag(), a, b);
let tcx = relation.tcx();
if tcx.features().generic_const_exprs() {
a = tcx.expand_abstract_consts(a);
b = tcx.expand_abstract_consts(b);
}
debug!("{}.structurally_relate_consts(normed_a = {:?}, normed_b = {:?})", relation.tag(), a, b);
// Currently, the values that can be unified are primitive types,
// and those that derive both `PartialEq` and `Eq`, corresponding
// to structural-match types.
let is_match = match (a.kind(), b.kind()) {
(ty::ConstKind::Infer(_), _) | (_, ty::ConstKind::Infer(_)) => {
// The caller should handle these cases!
panic!("var types encountered in structurally_relate_consts: {:?} {:?}", a, b)
}
(ty::ConstKind::Error(_), _) => return Ok(a),
(_, ty::ConstKind::Error(_)) => return Ok(b),
(ty::ConstKind::Param(a_p), ty::ConstKind::Param(b_p)) if a_p.index() == b_p.index() => {
// FIXME: Put this back
// debug_assert_eq!(a_p.name, b_p.name, "param types with same index differ in name");
true
}
(ty::ConstKind::Placeholder(p1), ty::ConstKind::Placeholder(p2)) => p1 == p2,
(ty::ConstKind::Value(_, a_val), ty::ConstKind::Value(_, b_val)) => a_val == b_val,
// While this is slightly incorrect, it shouldn't matter for `min_const_generics`
// and is the better alternative to waiting until `generic_const_exprs` can
// be stabilized.
(ty::ConstKind::Unevaluated(au), ty::ConstKind::Unevaluated(bu)) if au.def == bu.def => {
if cfg!(debug_assertions) {
let a_ty = tcx.type_of(au.def).instantiate(tcx, &au.args);
let b_ty = tcx.type_of(bu.def).instantiate(tcx, &bu.args);
assert_eq!(a_ty, b_ty);
}
let args = relation.relate_with_variance(
ty::Variance::Invariant,
VarianceDiagInfo::default(),
au.args,
bu.args,
)?;
return Ok(Const::new_unevaluated(tcx, ty::UnevaluatedConst { def: au.def, args }));
}
(ty::ConstKind::Expr(ae), ty::ConstKind::Expr(be)) => {
let expr = relation.relate(ae, be)?;
return Ok(Const::new_expr(tcx, expr));
}
_ => false,
};
if is_match { Ok(a) } else { Err(TypeError::ConstMismatch(ExpectedFound::new(true, a, b))) }
}
impl<I: Interner, T: Relate<I>> Relate<I> for ty::Binder<I, T> {
fn relate<R: TypeRelation<I>>(
relation: &mut R,
a: ty::Binder<I, T>,
b: ty::Binder<I, T>,
) -> RelateResult<I, ty::Binder<I, T>> {
relation.binders(a, b)
}
}
impl<I: Interner> Relate<I> for ty::PredicatePolarity {
fn relate<R: TypeRelation<I>>(
_relation: &mut R,
a: ty::PredicatePolarity,
b: ty::PredicatePolarity,
) -> RelateResult<I, ty::PredicatePolarity> {
if a != b {
Err(TypeError::PolarityMismatch(ExpectedFound::new(true, a, b)))
} else {
Ok(a)
}
}
}
impl<I: Interner> Relate<I> for ty::TraitPredicate<I> {
fn relate<R: TypeRelation<I>>(
relation: &mut R,
a: ty::TraitPredicate<I>,
b: ty::TraitPredicate<I>,
) -> RelateResult<I, ty::TraitPredicate<I>> {
Ok(ty::TraitPredicate {
trait_ref: relation.relate(a.trait_ref, b.trait_ref)?,
polarity: relation.relate(a.polarity, b.polarity)?,
})
}
}

View file

@ -20,7 +20,6 @@
pub type QueryResult<I> = Result<CanonicalResponse<I>, NoSolution>;
#[derive(Copy, Clone, Debug, Hash, PartialEq, Eq)]
#[derive(TypeFoldable_Generic, TypeVisitable_Generic)]
#[cfg_attr(feature = "nightly", derive(HashStable_NoContext))]
pub struct NoSolution;
@ -60,7 +59,7 @@ pub fn with<Q>(self, tcx: I, predicate: impl Upcast<I, Q>) -> Goal<I, Q> {
///
/// This is necessary as we treat nested goals different depending on
/// their source.
#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, TypeVisitable_Generic, TypeFoldable_Generic)]
#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)]
#[cfg_attr(feature = "nightly", derive(HashStable_NoContext))]
pub enum GoalSource {
Misc,
@ -170,7 +169,6 @@ pub enum CandidateSource<I: Interner> {
}
#[derive(Clone, Copy, Hash, PartialEq, Eq, Debug)]
#[derive(TypeVisitable_Generic, TypeFoldable_Generic)]
#[cfg_attr(feature = "nightly", derive(HashStable_NoContext, TyEncodable, TyDecodable))]
pub enum BuiltinImplSource {
/// Some builtin impl we don't need to differentiate. This should be used
@ -214,7 +212,6 @@ pub struct Response<I: Interner> {
}
#[derive(Clone, Copy, Hash, PartialEq, Eq, Debug)]
#[derive(TypeVisitable_Generic, TypeFoldable_Generic)]
#[cfg_attr(feature = "nightly", derive(HashStable_NoContext))]
pub enum Certainty {
Yes,
@ -252,7 +249,6 @@ pub const fn overflow(suggest_increasing_limit: bool) -> Certainty {
/// Why we failed to evaluate a goal.
#[derive(Clone, Copy, Hash, PartialEq, Eq, Debug)]
#[derive(TypeVisitable_Generic, TypeFoldable_Generic)]
#[cfg_attr(feature = "nightly", derive(HashStable_NoContext))]
pub enum MaybeCause {
/// We failed due to ambiguity. This ambiguity can either

View file

@ -212,6 +212,7 @@ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
macro_rules! impl_Display {
($($t:ident),* as $u:ident via $conv_fn:ident named $name:ident) => {
#[cfg(not(feature = "optimize_for_size"))]
fn $name(mut n: $u, is_nonnegative: bool, f: &mut fmt::Formatter<'_>) -> fmt::Result {
// 2^128 is about 3*10^38, so 39 gives an extra byte of space
let mut buf = [MaybeUninit::<u8>::uninit(); 39];
@ -277,6 +278,38 @@ fn $name(mut n: $u, is_nonnegative: bool, f: &mut fmt::Formatter<'_>) -> fmt::Re
f.pad_integral(is_nonnegative, "", buf_slice)
}
#[cfg(feature = "optimize_for_size")]
fn $name(mut n: $u, is_nonnegative: bool, f: &mut fmt::Formatter<'_>) -> fmt::Result {
// 2^128 is about 3*10^38, so 39 gives an extra byte of space
let mut buf = [MaybeUninit::<u8>::uninit(); 39];
let mut curr = buf.len();
let buf_ptr = MaybeUninit::slice_as_mut_ptr(&mut buf);
// SAFETY: To show that it's OK to copy into `buf_ptr`, notice that at the beginning
// `curr == buf.len() == 39 > log(n)` since `n < 2^128 < 10^39`, and at
// each step this is kept the same as `n` is divided. Since `n` is always
// non-negative, this means that `curr > 0` so `buf_ptr[curr..curr + 1]`
// is safe to access.
unsafe {
loop {
curr -= 1;
buf_ptr.add(curr).write((n % 10) as u8 + b'0');
n /= 10;
if n == 0 {
break;
}
}
}
// SAFETY: `curr` > 0 (since we made `buf` large enough), and all the chars are valid UTF-8
let buf_slice = unsafe {
str::from_utf8_unchecked(
slice::from_raw_parts(buf_ptr.add(curr), buf.len() - curr))
};
f.pad_integral(is_nonnegative, "", buf_slice)
}
$(#[stable(feature = "rust1", since = "1.0.0")]
impl fmt::Display for $t {
#[allow(unused_comparisons)]

View file

@ -16,7 +16,7 @@ fn foo(
fn skip_on_statements() {
#[rustfmt::skip]
{ 5+3; }
5+3;
}
#[rustfmt::skip]
@ -33,11 +33,11 @@ mod foo {
#[clippy::msrv = "1.29"]
fn msrv_1_29() {
#[cfg_attr(rustfmt, rustfmt::skip)]
{ 1+29; }
1+29;
}
#[clippy::msrv = "1.30"]
fn msrv_1_30() {
#[rustfmt::skip]
{ 1+30; }
1+30;
}

View file

@ -16,7 +16,7 @@ fn foo(
fn skip_on_statements() {
#[cfg_attr(rustfmt, rustfmt::skip)]
{ 5+3; }
5+3;
}
#[cfg_attr(rustfmt, rustfmt_skip)]
@ -33,11 +33,11 @@ pub fn f() {}
#[clippy::msrv = "1.29"]
fn msrv_1_29() {
#[cfg_attr(rustfmt, rustfmt::skip)]
{ 1+29; }
1+29;
}
#[clippy::msrv = "1.30"]
fn msrv_1_30() {
#[cfg_attr(rustfmt, rustfmt::skip)]
{ 1+30; }
1+30;
}

View file

@ -214,8 +214,8 @@ pub struct Params {
// #3313
fn stmt_expr_attributes() {
let foo ;
(#[must_use]
foo) = false ;
#[must_use]
foo = false ;
}
// #3509

View file

@ -248,8 +248,8 @@ pub struct Params {
// #3313
fn stmt_expr_attributes() {
let foo;
(#[must_use]
foo) = false;
#[must_use]
foo = false;
}
// #3509

View file

@ -13,17 +13,17 @@ fn syntax() {
let _ = #[attr] ();
let _ = #[attr] (#[attr] 0,);
let _ = #[attr] (#[attr] 0, 0);
let _ = (#[attr] 0) + #[attr] 0;
let _ = (#[attr] 0) / #[attr] 0;
let _ = (#[attr] 0) & #[attr] 0;
let _ = (#[attr] 0) % #[attr] 0;
let _ = #[attr] 0 + #[attr] 0;
let _ = #[attr] 0 / #[attr] 0;
let _ = #[attr] 0 & #[attr] 0;
let _ = #[attr] 0 % #[attr] 0;
let _ = #[attr] (0 + 0);
let _ = #[attr] !0;
let _ = #[attr] -0;
let _ = #[attr] false;
let _ = #[attr] 0;
let _ = #[attr] 'c';
let _ = (#[attr] x) as Y;
let _ = #[attr] x as Y;
let _ = #[attr] (x as Y);
let _ =
#[attr] while true {
@ -88,9 +88,9 @@ fn syntax() {
let _ = ();
foo
};
let _ = (#[attr] x) = y;
let _ = #[attr] x = y;
let _ = #[attr] (x = y);
let _ = (#[attr] x) += y;
let _ = #[attr] x += y;
let _ = #[attr] (x += y);
let _ = #[attr] foo.bar;
let _ = (#[attr] foo).bar;
@ -98,8 +98,8 @@ fn syntax() {
let _ = (#[attr] foo).0;
let _ = #[attr] foo[bar];
let _ = (#[attr] foo)[bar];
let _ = (#[attr] 0)..#[attr] 0;
let _ = (#[attr] 0)..;
let _ = #[attr] 0..#[attr] 0;
let _ = #[attr] 0..;
let _ = #[attr] (0..0);
let _ = #[attr] (0..);
let _ = #[attr] (..0);

View file

@ -147,13 +147,13 @@ fn _11() {
let _ = #[rustc_dummy] (0);
let _ = #[rustc_dummy] (0,);
let _ = #[rustc_dummy] (0, 0);
let _ = (#[rustc_dummy] 0) + #[rustc_dummy] 0;
let _ = #[rustc_dummy] 0 + #[rustc_dummy] 0;
let _ = #[rustc_dummy] !0;
let _ = #[rustc_dummy] -0i32;
let _ = #[rustc_dummy] false;
let _ = #[rustc_dummy] 'c';
let _ = #[rustc_dummy] 0;
let _ = (#[rustc_dummy] 0) as usize;
let _ = #[rustc_dummy] 0 as usize;
let _ =
#[rustc_dummy] while false {
#![rustc_dummy]
@ -208,8 +208,8 @@ fn _11() {
};
let const {} = #[rustc_dummy] const {};
let mut x = 0;
let _ = (#[rustc_dummy] x) = 15;
let _ = (#[rustc_dummy] x) += 15;
let _ = #[rustc_dummy] x = 15;
let _ = #[rustc_dummy] x += 15;
let s = Foo { data: () };
let _ = #[rustc_dummy] s.data;
let _ = (#[rustc_dummy] s).data;
@ -219,8 +219,8 @@ fn _11() {
let v = vec!(0);
let _ = #[rustc_dummy] v[0];
let _ = (#[rustc_dummy] v)[0];
let _ = (#[rustc_dummy] 0)..#[rustc_dummy] 0;
let _ = (#[rustc_dummy] 0)..;
let _ = #[rustc_dummy] 0..#[rustc_dummy] 0;
let _ = #[rustc_dummy] 0..;
let _ = #[rustc_dummy] (0..0);
let _ = #[rustc_dummy] (0..);
let _ = #[rustc_dummy] (..0);

View file

@ -1,3 +0,0 @@
extern crate foo;
fn main() {}

View file

@ -1 +0,0 @@
#![crate_name = "foo"]

View file

@ -1,28 +0,0 @@
// A path which contains the same rlib or dylib in two locations
// should not cause an assertion panic in the compiler.
// This test tries to replicate the linked issue and checks
// if the bugged error makes a resurgence.
// See https://github.com/rust-lang/rust/issues/11908
//@ ignore-cross-compile
use run_make_support::{dynamic_lib, rust_lib, rustc, tmp_dir};
use std::fs;
fn main() {
let tmp_dir_other = tmp_dir().join("other");
fs::create_dir(&tmp_dir_other);
rustc().input("foo.rs").crate_type("dylib").arg("-Cprefer-dynamic").run();
fs::rename(dynamic_lib("foo"), &tmp_dir_other);
rustc().input("foo.rs").crate_type("dylib").arg("-Cprefer-dynamic").run();
rustc().input("bar.rs").library_search_path(&tmp_dir_other).run();
fs::remove_dir_all(tmp_dir());
fs::create_dir_all(&tmp_dir_other);
rustc().input("foo.rs").crate_type("rlib").run();
fs::rename(rust_lib("foo"), &tmp_dir_other);
rustc().input("foo.rs").crate_type("rlib").run();
rustc().input("bar.rs").library_search_path(tmp_dir_other).run();
}

View file

@ -9,12 +9,16 @@ mod private_mod {
pub use std::env::{Args}; // braced-use has different item spans than unbraced
//~^ WARNING unreachable_pub
// we lint on struct definition
pub struct Hydrogen { //~ WARNING unreachable_pub
// `pub` struct fields, too
pub neutrons: usize, //~ WARNING unreachable_pub
// (... but not more-restricted fields)
// but not on fields, even if they are `pub` as putting `pub(crate)`
// it would clutter the source code for little value
pub neutrons: usize,
pub(crate) electrons: usize
}
pub(crate) struct Calcium {
pub neutrons: usize,
}
impl Hydrogen {
// impls, too
pub fn count_neutrons(&self) -> usize { self.neutrons } //~ WARNING unreachable_pub

View file

@ -24,7 +24,7 @@ LL | pub use std::env::{Args}; // braced-use has different item spans than u
= help: or consider exporting it for use by other crates
warning: unreachable `pub` item
--> $DIR/unreachable_pub.rs:12:5
--> $DIR/unreachable_pub.rs:13:5
|
LL | pub struct Hydrogen {
| ---^^^^^^^^^^^^^^^^
@ -33,16 +33,8 @@ LL | pub struct Hydrogen {
|
= help: or consider exporting it for use by other crates
warning: unreachable `pub` field
--> $DIR/unreachable_pub.rs:14:9
|
LL | pub neutrons: usize,
| ---^^^^^^^^^^^^^^^^
| |
| help: consider restricting its visibility: `pub(crate)`
warning: unreachable `pub` item
--> $DIR/unreachable_pub.rs:20:9
--> $DIR/unreachable_pub.rs:24:9
|
LL | pub fn count_neutrons(&self) -> usize { self.neutrons }
| ---^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@ -50,7 +42,7 @@ LL | pub fn count_neutrons(&self) -> usize { self.neutrons }
| help: consider restricting its visibility: `pub(crate)`
warning: unreachable `pub` item
--> $DIR/unreachable_pub.rs:29:5
--> $DIR/unreachable_pub.rs:33:5
|
LL | pub enum Helium {}
| ---^^^^^^^^^^^^
@ -60,7 +52,7 @@ LL | pub enum Helium {}
= help: or consider exporting it for use by other crates
warning: unreachable `pub` item
--> $DIR/unreachable_pub.rs:30:5
--> $DIR/unreachable_pub.rs:34:5
|
LL | pub union Lithium { c1: usize, c2: u8 }
| ---^^^^^^^^^^^^^^
@ -70,7 +62,7 @@ LL | pub union Lithium { c1: usize, c2: u8 }
= help: or consider exporting it for use by other crates
warning: unreachable `pub` item
--> $DIR/unreachable_pub.rs:31:5
--> $DIR/unreachable_pub.rs:35:5
|
LL | pub fn beryllium() {}
| ---^^^^^^^^^^^^^^^
@ -80,7 +72,7 @@ LL | pub fn beryllium() {}
= help: or consider exporting it for use by other crates
warning: unreachable `pub` item
--> $DIR/unreachable_pub.rs:32:5
--> $DIR/unreachable_pub.rs:36:5
|
LL | pub trait Boron {}
| ---^^^^^^^^^^^^
@ -90,7 +82,7 @@ LL | pub trait Boron {}
= help: or consider exporting it for use by other crates
warning: unreachable `pub` item
--> $DIR/unreachable_pub.rs:33:5
--> $DIR/unreachable_pub.rs:37:5
|
LL | pub const CARBON: usize = 1;
| ---^^^^^^^^^^^^^^^^^^^^
@ -100,7 +92,7 @@ LL | pub const CARBON: usize = 1;
= help: or consider exporting it for use by other crates
warning: unreachable `pub` item
--> $DIR/unreachable_pub.rs:34:5
--> $DIR/unreachable_pub.rs:38:5
|
LL | pub static NITROGEN: usize = 2;
| ---^^^^^^^^^^^^^^^^^^^^^^^
@ -110,7 +102,7 @@ LL | pub static NITROGEN: usize = 2;
= help: or consider exporting it for use by other crates
warning: unreachable `pub` item
--> $DIR/unreachable_pub.rs:35:5
--> $DIR/unreachable_pub.rs:39:5
|
LL | pub type Oxygen = bool;
| ---^^^^^^^^^^^^
@ -120,7 +112,7 @@ LL | pub type Oxygen = bool;
= help: or consider exporting it for use by other crates
warning: unreachable `pub` item
--> $DIR/unreachable_pub.rs:38:47
--> $DIR/unreachable_pub.rs:42:47
|
LL | ($visibility: vis, $name: ident) => { $visibility struct $name {} }
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^
@ -135,7 +127,7 @@ LL | define_empty_struct_with_visibility!(pub, Fluorine);
= note: this warning originates in the macro `define_empty_struct_with_visibility` (in Nightly builds, run with -Z macro-backtrace for more info)
warning: unreachable `pub` item
--> $DIR/unreachable_pub.rs:44:9
--> $DIR/unreachable_pub.rs:48:9
|
LL | pub fn catalyze() -> bool;
| ---^^^^^^^^^^^^^^^^^^^^^^
@ -144,5 +136,5 @@ LL | pub fn catalyze() -> bool;
|
= help: or consider exporting it for use by other crates
warning: 14 warnings emitted
warning: 13 warnings emitted

View file

@ -20,10 +20,10 @@ fn doc_comment_between_if_else(num: u8) -> bool {
}
fn doc_comment_on_expr(num: u8) -> bool {
(/// useless doc comment
/// useless doc comment
//~^ ERROR: attributes on expressions are experimental
//~| ERROR: unused doc comment
num) == 3
num == 3
}
fn doc_comment_on_expr_field() -> bool {

View file

@ -5,10 +5,10 @@ LL | else {
| ^^^^ expected expression
error[E0658]: attributes on expressions are experimental
--> $DIR/unused-doc-comments-edge-cases.rs:23:6
--> $DIR/unused-doc-comments-edge-cases.rs:23:5
|
LL | (/// useless doc comment
| ^^^^^^^^^^^^^^^^^^^^^^^
LL | /// useless doc comment
| ^^^^^^^^^^^^^^^^^^^^^^^
|
= note: see issue #15701 <https://github.com/rust-lang/rust/issues/15701> for more information
= help: add `#![feature(stmt_expr_attributes)]` to the crate attributes to enable
@ -32,12 +32,12 @@ LL | #![deny(unused_doc_comments)]
| ^^^^^^^^^^^^^^^^^^^
error: unused doc comment
--> $DIR/unused-doc-comments-edge-cases.rs:23:6
--> $DIR/unused-doc-comments-edge-cases.rs:23:5
|
LL | (/// useless doc comment
| ^^^^^^^^^^^^^^^^^^^^^^^
LL | /// useless doc comment
| ^^^^^^^^^^^^^^^^^^^^^^^
...
LL | num) == 3
LL | num == 3
| --- rustdoc does not generate documentation for expressions
|
= help: use `//` for a plain comment

View file

@ -1,15 +0,0 @@
//@ run-rustfix
#![feature(stmt_expr_attributes)]
#![allow(unused_assignments, unused_attributes)]
fn main() {
let mut x = (#[deprecated] 1) + 2; //~ ERROR ambiguous
(#[deprecated] x) = 4; //~ ERROR ambiguous
x = (#[deprecated] 5) as i32; //~ ERROR ambiguous
let _r = (#[deprecated] 1)..6; //~ ERROR ambiguous
println!("{}", x);
}

View file

@ -1,15 +0,0 @@
//@ run-rustfix
#![feature(stmt_expr_attributes)]
#![allow(unused_assignments, unused_attributes)]
fn main() {
let mut x = #[deprecated] 1 + 2; //~ ERROR ambiguous
#[deprecated] x = 4; //~ ERROR ambiguous
x = #[deprecated] 5 as i32; //~ ERROR ambiguous
let _r = #[deprecated] 1..6; //~ ERROR ambiguous
println!("{}", x);
}

View file

@ -1,46 +0,0 @@
error: ambiguous outer attributes
--> $DIR/attr-binary-expr-ambigous.rs:6:17
|
LL | let mut x = #[deprecated] 1 + 2;
| ^^^^^^^^^^^^^^^^^^^
|
help: wrap the expression in parentheses
|
LL | let mut x = (#[deprecated] 1) + 2;
| + +
error: ambiguous outer attributes
--> $DIR/attr-binary-expr-ambigous.rs:8:5
|
LL | #[deprecated] x = 4;
| ^^^^^^^^^^^^^^^^^^^
|
help: wrap the expression in parentheses
|
LL | (#[deprecated] x) = 4;
| + +
error: ambiguous outer attributes
--> $DIR/attr-binary-expr-ambigous.rs:10:9
|
LL | x = #[deprecated] 5 as i32;
| ^^^^^^^^^^^^^^^^^^^^^^
|
help: wrap the expression in parentheses
|
LL | x = (#[deprecated] 5) as i32;
| + +
error: ambiguous outer attributes
--> $DIR/attr-binary-expr-ambigous.rs:12:14
|
LL | let _r = #[deprecated] 1..6;
| ^^^^^^^^^^^^^^^^^^
|
help: wrap the expression in parentheses
|
LL | let _r = (#[deprecated] 1)..6;
| + +
error: aborting due to 4 previous errors

View file

@ -10,5 +10,6 @@
fn main() {
let _x;
let y = ();
(#[identity_attr] _x) = y;
#[identity_attr]
_x = y;
}