Auto merge of #125120 - compiler-errors:rollup-mnjybwv, r=compiler-errors

Rollup of 7 pull requests

Successful merges:

 - #119838 (style-guide: When breaking binops handle multi-line first operand better)
 - #124844 (Use a proper probe for shadowing impl)
 - #125047 (Migrate `run-make/issue-14500` to new `rmake.rs` format)
 - #125080 (only find segs chain for missing methods when no available candidates)
 - #125088 (Uplift `AliasTy` and `AliasTerm`)
 - #125100 (Don't do post-method-probe error reporting steps if we're in a suggestion)
 - #125118 (Use new utility functions/methods in run-make tests)

r? `@ghost`
`@rustbot` modify labels: rollup
This commit is contained in:
bors 2024-05-14 14:40:20 +00:00
commit ac385a5af6
42 changed files with 1042 additions and 599 deletions

View File

@ -106,6 +106,12 @@ impl<I: rustc_type_ir::Interner> IntoDiagArg for rustc_type_ir::ExistentialTrait
}
}
impl<I: rustc_type_ir::Interner> IntoDiagArg for rustc_type_ir::UnevaluatedConst<I> {
fn into_diag_arg(self) -> rustc_errors::DiagArgValue {
format!("{self:?}").into_diag_arg()
}
}
into_diag_arg_for_number!(i8, u8, i16, u16, i32, u32, i64, u64, i128, u128, isize, usize);
impl IntoDiagArg for bool {

View File

@ -938,14 +938,14 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
);
}
pub fn get_conversion_methods(
pub fn get_conversion_methods_for_diagnostic(
&self,
span: Span,
expected: Ty<'tcx>,
checked_ty: Ty<'tcx>,
hir_id: hir::HirId,
) -> Vec<AssocItem> {
let methods = self.probe_for_return_type(
let methods = self.probe_for_return_type_for_diagnostic(
span,
probe::Mode::MethodCall,
expected,

View File

@ -2414,7 +2414,12 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
let guar = if field.name == kw::Empty {
self.dcx().span_delayed_bug(field.span, "field name with no name")
} else if self.method_exists(field, base_ty, expr.hir_id, expected.only_has_type(self)) {
} else if self.method_exists_for_diagnostic(
field,
base_ty,
expr.hir_id,
expected.only_has_type(self),
) {
self.ban_take_value_of_method(expr, base_ty, field)
} else if !base_ty.is_primitive_ty() {
self.ban_nonexisting_field(field, base, expr, base_ty)
@ -2600,7 +2605,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
let mut err = self.private_field_err(field, base_did);
// Also check if an accessible method exists, which is often what is meant.
if self.method_exists(field, expr_t, expr.hir_id, return_ty)
if self.method_exists_for_diagnostic(field, expr_t, expr.hir_id, return_ty)
&& !self.expr_in_place(expr.hir_id)
{
self.suggest_method_call(

View File

@ -290,7 +290,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
expected_ty_expr: Option<&'tcx hir::Expr<'tcx>>,
) -> bool {
let expr = expr.peel_blocks();
let methods = self.get_conversion_methods(expr.span, expected, found, expr.hir_id);
let methods =
self.get_conversion_methods_for_diagnostic(expr.span, expected, found, expr.hir_id);
if let Some((suggestion, msg, applicability, verbose, annotation)) =
self.suggest_deref_or_ref(expr, found, expected)

View File

@ -91,7 +91,7 @@ pub enum CandidateSource {
impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
/// Determines whether the type `self_ty` supports a visible method named `method_name` or not.
#[instrument(level = "debug", skip(self))]
pub fn method_exists(
pub fn method_exists_for_diagnostic(
&self,
method_name: Ident,
self_ty: Ty<'tcx>,
@ -102,7 +102,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
probe::Mode::MethodCall,
method_name,
return_type,
IsSuggestion(false),
IsSuggestion(true),
self_ty,
call_expr_id,
ProbeScope::TraitsInScope,

View File

@ -90,6 +90,11 @@ pub(crate) struct ProbeContext<'a, 'tcx> {
>,
scope_expr_id: HirId,
/// Is this probe being done for a diagnostic? This will skip some error reporting
/// machinery, since we don't particularly care about, for example, similarly named
/// candidates if we're *reporting* similarly named candidates.
is_suggestion: IsSuggestion,
}
impl<'a, 'tcx> Deref for ProbeContext<'a, 'tcx> {
@ -220,7 +225,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
/// would use to decide if a method is a plausible fit for
/// ambiguity purposes).
#[instrument(level = "debug", skip(self, candidate_filter))]
pub fn probe_for_return_type(
pub fn probe_for_return_type_for_diagnostic(
&self,
span: Span,
mode: Mode,
@ -459,6 +464,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
&orig_values,
steps.steps,
scope_expr_id,
is_suggestion,
);
probe_cx.assemble_inherent_candidates();
@ -553,6 +559,7 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> {
orig_steps_var_values: &'a OriginalQueryValues<'tcx>,
steps: &'tcx [CandidateStep<'tcx>],
scope_expr_id: HirId,
is_suggestion: IsSuggestion,
) -> ProbeContext<'a, 'tcx> {
ProbeContext {
fcx,
@ -570,6 +577,7 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> {
static_candidates: RefCell::new(Vec::new()),
unsatisfied_predicates: RefCell::new(Vec::new()),
scope_expr_id,
is_suggestion,
}
}
@ -944,6 +952,18 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> {
return r;
}
// If it's a `lookup_probe_for_diagnostic`, then quit early. No need to
// probe for other candidates.
if self.is_suggestion.0 {
return Err(MethodError::NoMatch(NoMatchData {
static_candidates: vec![],
unsatisfied_predicates: vec![],
out_of_scope_traits: vec![],
similar_candidate: None,
mode: self.mode,
}));
}
debug!("pick: actual search failed, assemble diagnostics");
let static_candidates = std::mem::take(self.static_candidates.get_mut());
@ -1631,6 +1651,7 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> {
self.orig_steps_var_values,
self.steps,
self.scope_expr_id,
IsSuggestion(true),
);
pcx.allow_similar_names = true;
pcx.assemble_inherent_candidates();

View File

@ -1143,7 +1143,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
}
}
let label_span_not_found = |err: &mut Diag<'_>| {
let mut find_candidate_for_method = false;
let mut label_span_not_found = |err: &mut Diag<'_>| {
if unsatisfied_predicates.is_empty() {
err.span_label(span, format!("{item_kind} not found in `{ty_str}`"));
let is_string_or_ref_str = match rcvr_ty.kind() {
@ -1219,6 +1221,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
err.note(format!(
"the {item_kind} was found for\n{type_candidates}{additional_types}"
));
find_candidate_for_method = mode == Mode::MethodCall;
}
}
} else {
@ -1371,9 +1374,32 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
);
}
}
// If an appropriate error source is not found, check method chain for possible candiates
if unsatisfied_predicates.is_empty()
&& let Mode::MethodCall = mode
if !find_candidate_for_method {
self.lookup_segments_chain_for_no_match_method(
&mut err,
item_name,
item_kind,
source,
no_match_data,
);
}
self.note_derefed_ty_has_method(&mut err, source, rcvr_ty, item_name, expected);
Some(err)
}
/// If an appropriate error source is not found, check method chain for possible candidates
fn lookup_segments_chain_for_no_match_method(
&self,
err: &mut Diag<'_>,
item_name: Ident,
item_kind: &str,
source: SelfSource<'tcx>,
no_match_data: &NoMatchData<'tcx>,
) {
if no_match_data.unsatisfied_predicates.is_empty()
&& let Mode::MethodCall = no_match_data.mode
&& let SelfSource::MethodCall(mut source_expr) = source
{
let mut stack_methods = vec![];
@ -1394,6 +1420,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
.unwrap_or(Ty::new_misc_error(self.tcx)),
);
// FIXME: `probe_for_name_many` searches for methods in inherent implementations,
// so it may return a candidate that doesn't belong to this `revr_ty`. We need to
// check whether the instantiated type matches the received one.
for _matched_method in self.probe_for_name_many(
Mode::MethodCall,
item_name,
@ -1416,8 +1445,6 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
);
}
}
self.note_derefed_ty_has_method(&mut err, source, rcvr_ty, item_name, expected);
Some(err)
}
fn find_likely_intended_associated_item(
@ -2814,7 +2841,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
Some(output_ty) => self.resolve_vars_if_possible(output_ty),
_ => return,
};
let method_exists = self.method_exists(item_name, output_ty, call.hir_id, return_type);
let method_exists =
self.method_exists_for_diagnostic(item_name, output_ty, call.hir_id, return_type);
debug!("suggest_await_before_method: is_method_exist={}", method_exists);
if method_exists {
err.span_suggestion_verbose(

View File

@ -153,6 +153,8 @@ pub enum ProbeKind<'tcx> {
/// do a probe to find out what projection type(s) may be used to prove that
/// the source type upholds all of the target type's object bounds.
UpcastProjectionCompatibility,
/// Looking for param-env candidates that satisfy the trait ref for a projection.
ShadowedEnvProbing,
/// Try to unify an opaque type with an existing key in the storage.
OpaqueTypeStorageLookup { result: QueryResult<'tcx> },
}

View File

@ -118,6 +118,9 @@ impl<'a, 'b> ProofTreeFormatter<'a, 'b> {
ProbeKind::TraitCandidate { source, result } => {
write!(self.f, "CANDIDATE {source:?}: {result:?}")
}
ProbeKind::ShadowedEnvProbing => {
write!(self.f, "PROBING FOR IMPLS SHADOWED BY PARAM-ENV CANDIDATE:")
}
}?;
self.nested(|this| {

View File

@ -7,8 +7,7 @@ use rustc_hir as hir;
use rustc_hir::def::{DefKind, Res};
use rustc_hir::def_id::LocalDefId;
use rustc_macros::{HashStable, TyDecodable, TyEncodable};
use rustc_type_ir::ConstKind as IrConstKind;
use rustc_type_ir::{TypeFlags, WithCachedTypeInfo};
use rustc_type_ir::{self as ir, TypeFlags, WithCachedTypeInfo};
mod int;
mod kind;
@ -20,7 +19,8 @@ use rustc_span::Span;
use rustc_span::DUMMY_SP;
pub use valtree::*;
pub type ConstKind<'tcx> = IrConstKind<TyCtxt<'tcx>>;
pub type ConstKind<'tcx> = ir::ConstKind<TyCtxt<'tcx>>;
pub type UnevaluatedConst<'tcx> = ir::UnevaluatedConst<TyCtxt<'tcx>>;
#[cfg(target_pointer_width = "64")]
rustc_data_structures::static_assert_size!(ConstKind<'_>, 32);
@ -184,6 +184,14 @@ impl<'tcx> rustc_type_ir::inherent::Const<TyCtxt<'tcx>> for Const<'tcx> {
Const::new_bound(tcx, debruijn, var, ty)
}
fn new_unevaluated(
interner: TyCtxt<'tcx>,
uv: ty::UnevaluatedConst<'tcx>,
ty: Ty<'tcx>,
) -> Self {
Const::new_unevaluated(interner, uv, ty)
}
fn ty(self) -> Ty<'tcx> {
self.ty()
}

View File

@ -1,30 +1,15 @@
use super::Const;
use crate::mir;
use crate::ty::abstract_const::CastKind;
use crate::ty::GenericArgsRef;
use crate::ty::{self, visit::TypeVisitableExt as _, List, Ty, TyCtxt};
use rustc_hir::def_id::DefId;
use rustc_macros::{HashStable, TyDecodable, TyEncodable, TypeFoldable, TypeVisitable};
use rustc_macros::{extension, HashStable, TyDecodable, TyEncodable, TypeFoldable, TypeVisitable};
/// An unevaluated (potentially generic) constant used in the type-system.
#[derive(Copy, Clone, Eq, PartialEq, TyEncodable, TyDecodable)]
#[derive(Hash, HashStable, TypeFoldable, TypeVisitable)]
pub struct UnevaluatedConst<'tcx> {
pub def: DefId,
pub args: GenericArgsRef<'tcx>,
}
impl rustc_errors::IntoDiagArg for UnevaluatedConst<'_> {
fn into_diag_arg(self) -> rustc_errors::DiagArgValue {
format!("{self:?}").into_diag_arg()
}
}
impl<'tcx> UnevaluatedConst<'tcx> {
#[extension(pub(crate) trait UnevaluatedConstEvalExt<'tcx>)]
impl<'tcx> ty::UnevaluatedConst<'tcx> {
/// FIXME(RalfJung): I cannot explain what this does or why it makes sense, but not doing this
/// hurts performance.
#[inline]
pub(crate) fn prepare_for_eval(
fn prepare_for_eval(
self,
tcx: TyCtxt<'tcx>,
param_env: ty::ParamEnv<'tcx>,
@ -55,13 +40,6 @@ impl<'tcx> UnevaluatedConst<'tcx> {
}
}
impl<'tcx> UnevaluatedConst<'tcx> {
#[inline]
pub fn new(def: DefId, args: GenericArgsRef<'tcx>) -> UnevaluatedConst<'tcx> {
UnevaluatedConst { def, args }
}
}
#[derive(Copy, Clone, Eq, PartialEq, Hash)]
#[derive(HashStable, TyEncodable, TyDecodable, TypeVisitable, TypeFoldable)]
pub enum Expr<'tcx> {

View File

@ -76,6 +76,7 @@ use rustc_type_ir::TyKind::*;
use rustc_type_ir::WithCachedTypeInfo;
use rustc_type_ir::{CollectAndApply, Interner, TypeFlags};
use std::assert_matches::assert_matches;
use std::borrow::Borrow;
use std::cmp::Ordering;
use std::fmt;
@ -91,67 +92,124 @@ impl<'tcx> Interner for TyCtxt<'tcx> {
type DefiningOpaqueTypes = &'tcx ty::List<LocalDefId>;
type AdtDef = ty::AdtDef<'tcx>;
type GenericArgs = ty::GenericArgsRef<'tcx>;
type GenericArgsSlice = &'tcx [ty::GenericArg<'tcx>];
type GenericArg = ty::GenericArg<'tcx>;
type Term = ty::Term<'tcx>;
type Term = ty::Term<'tcx>;
type Binder<T: TypeVisitable<TyCtxt<'tcx>>> = Binder<'tcx, T>;
type BoundVars = &'tcx List<ty::BoundVariableKind>;
type BoundVar = ty::BoundVariableKind;
type CanonicalVars = CanonicalVarInfos<'tcx>;
type CanonicalVars = CanonicalVarInfos<'tcx>;
type Ty = Ty<'tcx>;
type Tys = &'tcx List<Ty<'tcx>>;
type AliasTy = ty::AliasTy<'tcx>;
type ParamTy = ParamTy;
type BoundTy = ty::BoundTy;
type PlaceholderTy = ty::PlaceholderType;
type ErrorGuaranteed = ErrorGuaranteed;
type ErrorGuaranteed = ErrorGuaranteed;
type BoundExistentialPredicates = &'tcx List<PolyExistentialPredicate<'tcx>>;
type PolyFnSig = PolyFnSig<'tcx>;
type AllocId = crate::mir::interpret::AllocId;
type Pat = Pattern<'tcx>;
type Pat = Pattern<'tcx>;
type Const = ty::Const<'tcx>;
type AliasConst = ty::UnevaluatedConst<'tcx>;
type PlaceholderConst = ty::PlaceholderConst;
type ParamConst = ty::ParamConst;
type BoundConst = ty::BoundVar;
type ValueConst = ty::ValTree<'tcx>;
type ExprConst = ty::Expr<'tcx>;
type ExprConst = ty::Expr<'tcx>;
type Region = Region<'tcx>;
type EarlyParamRegion = ty::EarlyParamRegion;
type LateParamRegion = ty::LateParamRegion;
type BoundRegion = ty::BoundRegion;
type InferRegion = ty::RegionVid;
type PlaceholderRegion = ty::PlaceholderRegion;
type PlaceholderRegion = ty::PlaceholderRegion;
type Predicate = Predicate<'tcx>;
type TraitPredicate = ty::TraitPredicate<'tcx>;
type RegionOutlivesPredicate = ty::RegionOutlivesPredicate<'tcx>;
type TypeOutlivesPredicate = ty::TypeOutlivesPredicate<'tcx>;
type ProjectionPredicate = ty::ProjectionPredicate<'tcx>;
type AliasTerm = ty::AliasTerm<'tcx>;
type NormalizesTo = ty::NormalizesTo<'tcx>;
type SubtypePredicate = ty::SubtypePredicate<'tcx>;
type CoercePredicate = ty::CoercePredicate<'tcx>;
type ClosureKind = ty::ClosureKind;
type Clauses = ty::Clauses<'tcx>;
type Clauses = ty::Clauses<'tcx>;
fn mk_canonical_var_infos(self, infos: &[ty::CanonicalVarInfo<Self>]) -> Self::CanonicalVars {
self.mk_canonical_var_infos(infos)
}
type GenericsOf = &'tcx ty::Generics;
fn generics_of(self, def_id: DefId) -> &'tcx ty::Generics {
self.generics_of(def_id)
}
fn type_of_instantiated(self, def_id: DefId, args: ty::GenericArgsRef<'tcx>) -> Ty<'tcx> {
self.type_of(def_id).instantiate(self, args)
}
fn alias_ty_kind(self, alias: ty::AliasTy<'tcx>) -> ty::AliasTyKind {
match self.def_kind(alias.def_id) {
DefKind::AssocTy => {
if let DefKind::Impl { of_trait: false } = self.def_kind(self.parent(alias.def_id))
{
ty::Inherent
} else {
ty::Projection
}
}
DefKind::OpaqueTy => ty::Opaque,
DefKind::TyAlias => ty::Weak,
kind => bug!("unexpected DefKind in AliasTy: {kind:?}"),
}
}
fn alias_term_kind(self, alias: ty::AliasTerm<'tcx>) -> ty::AliasTermKind {
match self.def_kind(alias.def_id) {
DefKind::AssocTy => {
if let DefKind::Impl { of_trait: false } = self.def_kind(self.parent(alias.def_id))
{
ty::AliasTermKind::InherentTy
} else {
ty::AliasTermKind::ProjectionTy
}
}
DefKind::OpaqueTy => ty::AliasTermKind::OpaqueTy,
DefKind::TyAlias => ty::AliasTermKind::WeakTy,
DefKind::AssocConst => ty::AliasTermKind::ProjectionConst,
DefKind::AnonConst => ty::AliasTermKind::UnevaluatedConst,
kind => bug!("unexpected DefKind in AliasTy: {kind:?}"),
}
}
fn trait_ref_and_own_args_for_alias(
self,
def_id: Self::DefId,
args: Self::GenericArgs,
) -> (rustc_type_ir::TraitRef<Self>, Self::GenericArgsSlice) {
assert_matches!(self.def_kind(def_id), DefKind::AssocTy | DefKind::AssocConst);
let trait_def_id = self.parent(def_id);
assert_matches!(self.def_kind(trait_def_id), DefKind::Trait);
let trait_generics = self.generics_of(trait_def_id);
(
ty::TraitRef::new(self, trait_def_id, args.truncate_to(self, trait_generics)),
&args[trait_generics.count()..],
)
}
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 {
self.mk_args_from_iter(args)
}
fn check_and_mk_args(
self,
def_id: DefId,

View File

@ -96,9 +96,9 @@ pub use self::list::{List, ListWithCachedTypeInfo};
pub use self::parameterized::ParameterizedOverTcx;
pub use self::pattern::{Pattern, PatternKind};
pub use self::predicate::{
Clause, ClauseKind, CoercePredicate, ExistentialPredicate, ExistentialPredicateStableCmpExt,
ExistentialProjection, ExistentialTraitRef, NormalizesTo, OutlivesPredicate,
PolyCoercePredicate, PolyExistentialPredicate, PolyExistentialProjection,
AliasTerm, Clause, ClauseKind, CoercePredicate, ExistentialPredicate,
ExistentialPredicateStableCmpExt, ExistentialProjection, ExistentialTraitRef, NormalizesTo,
OutlivesPredicate, PolyCoercePredicate, PolyExistentialPredicate, PolyExistentialProjection,
PolyExistentialTraitRef, PolyProjectionPredicate, PolyRegionOutlivesPredicate,
PolySubtypePredicate, PolyTraitPredicate, PolyTraitRef, PolyTypeOutlivesPredicate, Predicate,
PredicateKind, ProjectionPredicate, RegionOutlivesPredicate, SubtypePredicate, ToPolyTraitRef,
@ -110,11 +110,11 @@ pub use self::region::{
};
pub use self::rvalue_scopes::RvalueScopes;
pub use self::sty::{
AliasTerm, AliasTy, Article, Binder, BoundTy, BoundTyKind, BoundVariableKind,
CanonicalPolyFnSig, ClosureArgs, ClosureArgsParts, CoroutineArgs, CoroutineArgsParts,
CoroutineClosureArgs, CoroutineClosureArgsParts, CoroutineClosureSignature, FnSig, GenSig,
InlineConstArgs, InlineConstArgsParts, ParamConst, ParamTy, PolyFnSig, TyKind, TypeAndMut,
UpvarArgs, VarianceDiagInfo,
AliasTy, Article, Binder, BoundTy, BoundTyKind, BoundVariableKind, CanonicalPolyFnSig,
ClosureArgs, ClosureArgsParts, CoroutineArgs, CoroutineArgsParts, CoroutineClosureArgs,
CoroutineClosureArgsParts, CoroutineClosureSignature, FnSig, GenSig, InlineConstArgs,
InlineConstArgsParts, ParamConst, ParamTy, PolyFnSig, TyKind, TypeAndMut, UpvarArgs,
VarianceDiagInfo,
};
pub use self::trait_def::TraitDef;
pub use self::typeck_results::{

View File

@ -13,6 +13,7 @@ use crate::ty::{
};
pub type TraitRef<'tcx> = ir::TraitRef<TyCtxt<'tcx>>;
pub type AliasTerm<'tcx> = ir::AliasTerm<TyCtxt<'tcx>>;
pub type ProjectionPredicate<'tcx> = ir::ProjectionPredicate<TyCtxt<'tcx>>;
pub type ExistentialPredicate<'tcx> = ir::ExistentialPredicate<TyCtxt<'tcx>>;
pub type ExistentialTraitRef<'tcx> = ir::ExistentialTraitRef<TyCtxt<'tcx>>;

View File

@ -3038,6 +3038,33 @@ define_print! {
p!(write("<{} as {}>", self.self_ty(), self.print_only_trait_path()))
}
ty::AliasTy<'tcx> {
let alias_term: ty::AliasTerm<'tcx> = (*self).into();
p!(print(alias_term))
}
ty::AliasTerm<'tcx> {
match self.kind(cx.tcx()) {
ty::AliasTermKind::InherentTy => p!(pretty_print_inherent_projection(*self)),
ty::AliasTermKind::ProjectionTy
| ty::AliasTermKind::WeakTy
| ty::AliasTermKind::OpaqueTy
| ty::AliasTermKind::UnevaluatedConst
| ty::AliasTermKind::ProjectionConst => {
// If we're printing verbosely, or don't want to invoke queries
// (`is_impl_trait_in_trait`), then fall back to printing the def path.
// This is likely what you want if you're debugging the compiler anyways.
if !(cx.should_print_verbose() || with_reduced_queries())
&& cx.tcx().is_impl_trait_in_trait(self.def_id)
{
return cx.pretty_print_opaque_impl_type(self.def_id, self.args);
} else {
p!(print_def_path(self.def_id, self.args));
}
}
}
}
ty::TraitPredicate<'tcx> {
p!(print(self.trait_ref.self_ty()), ": ");
p!(pretty_print_bound_constness(self.trait_ref));
@ -3205,33 +3232,6 @@ define_print_and_forward_display! {
}
}
ty::AliasTy<'tcx> {
let alias_term: ty::AliasTerm<'tcx> = (*self).into();
p!(print(alias_term))
}
ty::AliasTerm<'tcx> {
match self.kind(cx.tcx()) {
ty::AliasTermKind::InherentTy => p!(pretty_print_inherent_projection(*self)),
ty::AliasTermKind::ProjectionTy
| ty::AliasTermKind::WeakTy
| ty::AliasTermKind::OpaqueTy
| ty::AliasTermKind::UnevaluatedConst
| ty::AliasTermKind::ProjectionConst => {
// If we're printing verbosely, or don't want to invoke queries
// (`is_impl_trait_in_trait`), then fall back to printing the def path.
// This is likely what you want if you're debugging the compiler anyways.
if !(cx.should_print_verbose() || with_reduced_queries())
&& cx.tcx().is_impl_trait_in_trait(self.def_id)
{
return cx.pretty_print_opaque_impl_type(self.def_id, self.args);
} else {
p!(print_def_path(self.def_id, self.args));
}
}
}
}
ty::Predicate<'tcx> {
p!(print(self.kind()))
}

View File

@ -7,7 +7,7 @@ use crate::mir::interpret;
use crate::ty::fold::{FallibleTypeFolder, TypeFoldable, TypeSuperFoldable};
use crate::ty::print::{with_no_trimmed_paths, FmtPrinter, Printer};
use crate::ty::visit::{TypeSuperVisitable, TypeVisitable, TypeVisitor};
use crate::ty::{self, AliasTy, InferConst, Lift, Term, TermKind, Ty, TyCtxt};
use crate::ty::{self, InferConst, Lift, Term, TermKind, Ty, TyCtxt};
use rustc_ast_ir::try_visit;
use rustc_ast_ir::visit::VisitorResult;
use rustc_hir::def::Namespace;
@ -164,23 +164,6 @@ impl<'tcx> fmt::Debug for ty::Clause<'tcx> {
}
}
impl<'tcx> fmt::Debug for AliasTy<'tcx> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
WithInfcx::with_no_infcx(self).fmt(f)
}
}
impl<'tcx> DebugWithInfcx<TyCtxt<'tcx>> for AliasTy<'tcx> {
fn fmt<Infcx: InferCtxtLike<Interner = TyCtxt<'tcx>>>(
this: WithInfcx<'_, Infcx, &Self>,
f: &mut core::fmt::Formatter<'_>,
) -> core::fmt::Result {
f.debug_struct("AliasTy")
.field("args", &this.map(|data| data.args))
.field("def_id", &this.data.def_id)
.finish()
}
}
impl<'tcx> DebugWithInfcx<TyCtxt<'tcx>> for Pattern<'tcx> {
fn fmt<Infcx: InferCtxtLike<Interner = TyCtxt<'tcx>>>(
this: WithInfcx<'_, Infcx, &Self>,
@ -230,23 +213,6 @@ impl<'tcx> DebugWithInfcx<TyCtxt<'tcx>> for ty::consts::Expr<'tcx> {
}
}
impl<'tcx> fmt::Debug for ty::UnevaluatedConst<'tcx> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
WithInfcx::with_no_infcx(self).fmt(f)
}
}
impl<'tcx> DebugWithInfcx<TyCtxt<'tcx>> for ty::UnevaluatedConst<'tcx> {
fn fmt<Infcx: InferCtxtLike<Interner = TyCtxt<'tcx>>>(
this: WithInfcx<'_, Infcx, &Self>,
f: &mut core::fmt::Formatter<'_>,
) -> core::fmt::Result {
f.debug_struct("UnevaluatedConst")
.field("def", &this.data.def)
.field("args", &this.wrap(this.data.args))
.finish()
}
}
impl<'tcx> fmt::Debug for ty::Const<'tcx> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
WithInfcx::with_no_infcx(self).fmt(f)

View File

@ -28,20 +28,17 @@ use std::iter;
use std::ops::{ControlFlow, Deref, Range};
use ty::util::IntTypeExt;
use rustc_type_ir::BoundVar;
use rustc_type_ir::CollectAndApply;
use rustc_type_ir::DynKind;
use rustc_type_ir::TyKind as IrTyKind;
use rustc_type_ir::TyKind::*;
use rustc_type_ir::TypeAndMut as IrTypeAndMut;
use rustc_type_ir::{self as ir, BoundVar, CollectAndApply, DynKind};
use super::fold::FnMutDelegate;
use super::GenericParamDefKind;
// Re-export and re-parameterize some `I = TyCtxt<'tcx>` types here
#[rustc_diagnostic_item = "TyKind"]
pub type TyKind<'tcx> = IrTyKind<TyCtxt<'tcx>>;
pub type TypeAndMut<'tcx> = IrTypeAndMut<TyCtxt<'tcx>>;
pub type TyKind<'tcx> = ir::TyKind<TyCtxt<'tcx>>;
pub type TypeAndMut<'tcx> = ir::TypeAndMut<TyCtxt<'tcx>>;
pub type AliasTy<'tcx> = ir::AliasTy<TyCtxt<'tcx>>;
pub trait Article {
fn article(&self) -> &'static str;
@ -1105,371 +1102,6 @@ where
}
}
/// Represents the unprojected term of a projection goal.
///
/// * For a projection, this would be `<Ty as Trait<...>>::N<...>`.
/// * For an inherent projection, this would be `Ty::N<...>`.
/// * For an opaque type, there is no explicit syntax.
#[derive(Copy, Clone, PartialEq, Eq, Hash, TyEncodable, TyDecodable)]
#[derive(HashStable, TypeFoldable, TypeVisitable, Lift)]
pub struct AliasTerm<'tcx> {
/// The parameters of the associated or opaque item.
///
/// For a projection, these are the generic parameters for the trait and the
/// GAT parameters, if there are any.
///
/// For an inherent projection, they consist of the self type and the GAT parameters,
/// if there are any.
///
/// For RPIT the generic parameters are for the generics of the function,
/// while for TAIT it is used for the generic parameters of the alias.
pub args: GenericArgsRef<'tcx>,
/// The `DefId` of the `TraitItem` or `ImplItem` for the associated type `N` depending on whether
/// this is a projection or an inherent projection or the `DefId` of the `OpaqueType` item if
/// this is an opaque.
///
/// During codegen, `tcx.type_of(def_id)` can be used to get the type of the
/// underlying type if the type is an opaque.
///
/// Note that if this is an associated type, this is not the `DefId` of the
/// `TraitRef` containing this associated type, which is in `tcx.associated_item(def_id).container`,
/// aka. `tcx.parent(def_id)`.
pub def_id: DefId,
/// This field exists to prevent the creation of `AliasTerm` without using
/// [AliasTerm::new].
_use_alias_term_new_instead: (),
}
// FIXME: Remove these when we uplift `AliasTerm`
use crate::ty::{DebugWithInfcx, InferCtxtLike, WithInfcx};
impl<'tcx> std::fmt::Debug for AliasTerm<'tcx> {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
WithInfcx::with_no_infcx(self).fmt(f)
}
}
impl<'tcx> DebugWithInfcx<TyCtxt<'tcx>> for AliasTerm<'tcx> {
fn fmt<Infcx: InferCtxtLike<Interner = TyCtxt<'tcx>>>(
this: WithInfcx<'_, Infcx, &Self>,
f: &mut std::fmt::Formatter<'_>,
) -> std::fmt::Result {
f.debug_struct("AliasTerm")
.field("args", &this.map(|data| data.args))
.field("def_id", &this.data.def_id)
.finish()
}
}
impl<'tcx> rustc_type_ir::inherent::AliasTerm<TyCtxt<'tcx>> for AliasTerm<'tcx> {
fn new(
interner: TyCtxt<'tcx>,
trait_def_id: DefId,
args: impl IntoIterator<Item: Into<ty::GenericArg<'tcx>>>,
) -> Self {
AliasTerm::new(interner, trait_def_id, args)
}
fn def_id(self) -> DefId {
self.def_id
}
fn args(self) -> ty::GenericArgsRef<'tcx> {
self.args
}
fn trait_def_id(self, interner: TyCtxt<'tcx>) -> DefId {
self.trait_def_id(interner)
}
fn self_ty(self) -> Ty<'tcx> {
self.self_ty()
}
fn with_self_ty(self, tcx: TyCtxt<'tcx>, self_ty: Ty<'tcx>) -> Self {
self.with_self_ty(tcx, self_ty)
}
}
impl<'tcx> AliasTerm<'tcx> {
pub fn new(
tcx: TyCtxt<'tcx>,
def_id: DefId,
args: impl IntoIterator<Item: Into<GenericArg<'tcx>>>,
) -> AliasTerm<'tcx> {
let args = tcx.check_and_mk_args(def_id, args);
AliasTerm { def_id, args, _use_alias_term_new_instead: () }
}
pub fn expect_ty(self, tcx: TyCtxt<'tcx>) -> AliasTy<'tcx> {
match self.kind(tcx) {
ty::AliasTermKind::ProjectionTy
| ty::AliasTermKind::InherentTy
| ty::AliasTermKind::OpaqueTy
| ty::AliasTermKind::WeakTy => {}
ty::AliasTermKind::UnevaluatedConst | ty::AliasTermKind::ProjectionConst => {
bug!("Cannot turn `UnevaluatedConst` into `AliasTy`")
}
}
ty::AliasTy { def_id: self.def_id, args: self.args, _use_alias_ty_new_instead: () }
}
pub fn kind(self, tcx: TyCtxt<'tcx>) -> ty::AliasTermKind {
match tcx.def_kind(self.def_id) {
DefKind::AssocTy => {
if let DefKind::Impl { of_trait: false } = tcx.def_kind(tcx.parent(self.def_id)) {
ty::AliasTermKind::InherentTy
} else {
ty::AliasTermKind::ProjectionTy
}
}
DefKind::OpaqueTy => ty::AliasTermKind::OpaqueTy,
DefKind::TyAlias => ty::AliasTermKind::WeakTy,
DefKind::AnonConst => ty::AliasTermKind::UnevaluatedConst,
DefKind::AssocConst => ty::AliasTermKind::ProjectionConst,
kind => bug!("unexpected DefKind in AliasTy: {kind:?}"),
}
}
}
/// The following methods work only with (trait) associated item projections.
impl<'tcx> AliasTerm<'tcx> {
pub fn self_ty(self) -> Ty<'tcx> {
self.args.type_at(0)
}
pub fn with_self_ty(self, tcx: TyCtxt<'tcx>, self_ty: Ty<'tcx>) -> Self {
AliasTerm::new(
tcx,
self.def_id,
[self_ty.into()].into_iter().chain(self.args.iter().skip(1)),
)
}
pub fn trait_def_id(self, tcx: TyCtxt<'tcx>) -> DefId {
match tcx.def_kind(self.def_id) {
DefKind::AssocTy | DefKind::AssocConst => tcx.parent(self.def_id),
kind => bug!("expected a projection AliasTy; found {kind:?}"),
}
}
/// Extracts the underlying trait reference from this projection.
/// For example, if this is a projection of `<T as Iterator>::Item`,
/// then this function would return a `T: Iterator` trait reference.
///
/// NOTE: This will drop the args for generic associated types
/// consider calling [Self::trait_ref_and_own_args] to get those
/// as well.
pub fn trait_ref(self, tcx: TyCtxt<'tcx>) -> ty::TraitRef<'tcx> {
let def_id = self.trait_def_id(tcx);
ty::TraitRef::new(tcx, def_id, self.args.truncate_to(tcx, tcx.generics_of(def_id)))
}
/// Extracts the underlying trait reference and own args from this projection.
/// For example, if this is a projection of `<T as StreamingIterator>::Item<'a>`,
/// then this function would return a `T: StreamingIterator` trait reference and `['a]` as the own args
pub fn trait_ref_and_own_args(
self,
tcx: TyCtxt<'tcx>,
) -> (ty::TraitRef<'tcx>, &'tcx [ty::GenericArg<'tcx>]) {
let trait_def_id = self.trait_def_id(tcx);
let trait_generics = tcx.generics_of(trait_def_id);
(
ty::TraitRef::new(tcx, trait_def_id, self.args.truncate_to(tcx, trait_generics)),
&self.args[trait_generics.count()..],
)
}
pub fn to_term(self, tcx: TyCtxt<'tcx>) -> ty::Term<'tcx> {
match self.kind(tcx) {
ty::AliasTermKind::ProjectionTy => Ty::new_alias(
tcx,
ty::Projection,
AliasTy { def_id: self.def_id, args: self.args, _use_alias_ty_new_instead: () },
)
.into(),
ty::AliasTermKind::InherentTy => Ty::new_alias(
tcx,
ty::Inherent,
AliasTy { def_id: self.def_id, args: self.args, _use_alias_ty_new_instead: () },
)
.into(),
ty::AliasTermKind::OpaqueTy => Ty::new_alias(
tcx,
ty::Opaque,
AliasTy { def_id: self.def_id, args: self.args, _use_alias_ty_new_instead: () },
)
.into(),
ty::AliasTermKind::WeakTy => Ty::new_alias(
tcx,
ty::Weak,
AliasTy { def_id: self.def_id, args: self.args, _use_alias_ty_new_instead: () },
)
.into(),
ty::AliasTermKind::UnevaluatedConst | ty::AliasTermKind::ProjectionConst => {
ty::Const::new_unevaluated(
tcx,
ty::UnevaluatedConst::new(self.def_id, self.args),
tcx.type_of(self.def_id).instantiate(tcx, self.args),
)
.into()
}
}
}
}
impl<'tcx> From<AliasTy<'tcx>> for AliasTerm<'tcx> {
fn from(ty: AliasTy<'tcx>) -> Self {
AliasTerm { args: ty.args, def_id: ty.def_id, _use_alias_term_new_instead: () }
}
}
impl<'tcx> From<ty::UnevaluatedConst<'tcx>> for AliasTerm<'tcx> {
fn from(ct: ty::UnevaluatedConst<'tcx>) -> Self {
AliasTerm { args: ct.args, def_id: ct.def, _use_alias_term_new_instead: () }
}
}
/// Represents the projection of an associated, opaque, or lazy-type-alias type.
///
/// * For a projection, this would be `<Ty as Trait<...>>::N<...>`.
/// * For an inherent projection, this would be `Ty::N<...>`.
/// * For an opaque type, there is no explicit syntax.
#[derive(Copy, Clone, PartialEq, Eq, Hash, TyEncodable, TyDecodable)]
#[derive(HashStable, TypeFoldable, TypeVisitable, Lift)]
pub struct AliasTy<'tcx> {
/// The parameters of the associated or opaque type.
///
/// For a projection, these are the generic parameters for the trait and the
/// GAT parameters, if there are any.
///
/// For an inherent projection, they consist of the self type and the GAT parameters,
/// if there are any.
///
/// For RPIT the generic parameters are for the generics of the function,
/// while for TAIT it is used for the generic parameters of the alias.
pub args: GenericArgsRef<'tcx>,
/// The `DefId` of the `TraitItem` or `ImplItem` for the associated type `N` depending on whether
/// this is a projection or an inherent projection or the `DefId` of the `OpaqueType` item if
/// this is an opaque.
///
/// During codegen, `tcx.type_of(def_id)` can be used to get the type of the
/// underlying type if the type is an opaque.
///
/// Note that if this is an associated type, this is not the `DefId` of the
/// `TraitRef` containing this associated type, which is in `tcx.associated_item(def_id).container`,
/// aka. `tcx.parent(def_id)`.
pub def_id: DefId,
/// This field exists to prevent the creation of `AliasT` without using
/// [AliasTy::new].
_use_alias_ty_new_instead: (),
}
impl<'tcx> AliasTy<'tcx> {
pub fn new(
tcx: TyCtxt<'tcx>,
def_id: DefId,
args: impl IntoIterator<Item: Into<GenericArg<'tcx>>>,
) -> ty::AliasTy<'tcx> {
let args = tcx.check_and_mk_args(def_id, args);
ty::AliasTy { def_id, args, _use_alias_ty_new_instead: () }
}
pub fn kind(self, tcx: TyCtxt<'tcx>) -> ty::AliasTyKind {
match tcx.def_kind(self.def_id) {
DefKind::AssocTy
if let DefKind::Impl { of_trait: false } =
tcx.def_kind(tcx.parent(self.def_id)) =>
{
ty::Inherent
}
DefKind::AssocTy => ty::Projection,
DefKind::OpaqueTy => ty::Opaque,
DefKind::TyAlias => ty::Weak,
kind => bug!("unexpected DefKind in AliasTy: {kind:?}"),
}
}
/// Whether this alias type is an opaque.
pub fn is_opaque(self, tcx: TyCtxt<'tcx>) -> bool {
matches!(self.kind(tcx), ty::Opaque)
}
pub fn to_ty(self, tcx: TyCtxt<'tcx>) -> Ty<'tcx> {
Ty::new_alias(tcx, self.kind(tcx), self)
}
}
/// The following methods work only with (trait) associated type projections.
impl<'tcx> AliasTy<'tcx> {
pub fn self_ty(self) -> Ty<'tcx> {
self.args.type_at(0)
}
pub fn with_self_ty(self, tcx: TyCtxt<'tcx>, self_ty: Ty<'tcx>) -> Self {
AliasTy::new(tcx, self.def_id, [self_ty.into()].into_iter().chain(self.args.iter().skip(1)))
}
pub fn trait_def_id(self, tcx: TyCtxt<'tcx>) -> DefId {
match tcx.def_kind(self.def_id) {
DefKind::AssocTy | DefKind::AssocConst => tcx.parent(self.def_id),
kind => bug!("expected a projection AliasTy; found {kind:?}"),
}
}
/// Extracts the underlying trait reference and own args from this projection.
/// For example, if this is a projection of `<T as StreamingIterator>::Item<'a>`,
/// then this function would return a `T: StreamingIterator` trait reference and `['a]` as the own args
pub fn trait_ref_and_own_args(
self,
tcx: TyCtxt<'tcx>,
) -> (ty::TraitRef<'tcx>, &'tcx [ty::GenericArg<'tcx>]) {
let trait_def_id = self.trait_def_id(tcx);
let trait_generics = tcx.generics_of(trait_def_id);
(
ty::TraitRef::new(tcx, trait_def_id, self.args.truncate_to(tcx, trait_generics)),
&self.args[trait_generics.count()..],
)
}
/// Extracts the underlying trait reference from this projection.
/// For example, if this is a projection of `<T as Iterator>::Item`,
/// then this function would return a `T: Iterator` trait reference.
///
/// WARNING: This will drop the args for generic associated types
/// consider calling [Self::trait_ref_and_own_args] to get those
/// as well.
pub fn trait_ref(self, tcx: TyCtxt<'tcx>) -> ty::TraitRef<'tcx> {
let def_id = self.trait_def_id(tcx);
ty::TraitRef::new(tcx, def_id, self.args.truncate_to(tcx, tcx.generics_of(def_id)))
}
}
/// The following methods work only with inherent associated type projections.
impl<'tcx> AliasTy<'tcx> {
/// Transform the generic parameters to have the given `impl` args as the base and the GAT args on top of that.
///
/// Does the following transformation:
///
/// ```text
/// [Self, P_0...P_m] -> [I_0...I_n, P_0...P_m]
///
/// I_i impl args
/// P_j GAT args
/// ```
pub fn rebase_inherent_args_onto_impl(
self,
impl_args: ty::GenericArgsRef<'tcx>,
tcx: TyCtxt<'tcx>,
) -> ty::GenericArgsRef<'tcx> {
debug_assert_eq!(self.kind(tcx), ty::Inherent);
tcx.mk_args_from_iter(impl_args.into_iter().chain(self.args.into_iter().skip(1)))
}
}
#[derive(Copy, Clone, Debug, TypeFoldable, TypeVisitable)]
pub struct GenSig<'tcx> {
pub resume_ty: Ty<'tcx>,
@ -2020,6 +1652,14 @@ impl<'tcx> rustc_type_ir::inherent::Ty<TyCtxt<'tcx>> for Ty<'tcx> {
fn new_anon_bound(tcx: TyCtxt<'tcx>, debruijn: ty::DebruijnIndex, var: ty::BoundVar) -> Self {
Ty::new_bound(tcx, debruijn, ty::BoundTy { var, kind: ty::BoundTyKind::Anon })
}
fn new_alias(
interner: TyCtxt<'tcx>,
kind: ty::AliasTyKind,
alias_ty: ty::AliasTy<'tcx>,
) -> Self {
Ty::new_alias(interner, kind, alias_ty)
}
}
/// Type utilities

View File

@ -1,7 +1,7 @@
//! Code shared by trait and projection goals for candidate assembly.
use crate::solve::GoalSource;
use crate::solve::{inspect, EvalCtxt, SolverMode};
use crate::solve::{EvalCtxt, SolverMode};
use rustc_hir::def_id::DefId;
use rustc_infer::traits::query::NoSolution;
use rustc_middle::bug;
@ -16,7 +16,6 @@ use rustc_middle::ty::{fast_reject, TypeFoldable};
use rustc_middle::ty::{ToPredicate, TypeVisitableExt};
use rustc_span::{ErrorGuaranteed, DUMMY_SP};
use std::fmt::Debug;
use std::mem;
pub(super) mod structural_traits;
@ -792,17 +791,16 @@ impl<'tcx> EvalCtxt<'_, 'tcx> {
goal: Goal<'tcx, G>,
candidates: &mut Vec<Candidate<'tcx>>,
) {
// HACK: We temporarily remove the `ProofTreeBuilder` to
// avoid adding `Trait` candidates to the candidates used
// to prove the current goal.
let inspect = mem::replace(&mut self.inspect, inspect::ProofTreeBuilder::new_noop());
let tcx = self.tcx();
let trait_goal: Goal<'tcx, ty::TraitPredicate<'tcx>> =
goal.with(tcx, goal.predicate.trait_ref(tcx));
let mut trait_candidates_from_env = Vec::new();
self.assemble_param_env_candidates(trait_goal, &mut trait_candidates_from_env);
self.assemble_alias_bound_candidates(trait_goal, &mut trait_candidates_from_env);
let mut trait_candidates_from_env = vec![];
self.probe(|_| ProbeKind::ShadowedEnvProbing).enter(|ecx| {
ecx.assemble_param_env_candidates(trait_goal, &mut trait_candidates_from_env);
ecx.assemble_alias_bound_candidates(trait_goal, &mut trait_candidates_from_env);
});
if !trait_candidates_from_env.is_empty() {
let trait_env_result = self.merge_candidates(trait_candidates_from_env);
match trait_env_result.unwrap().value.certainty {
@ -831,7 +829,6 @@ impl<'tcx> EvalCtxt<'_, 'tcx> {
}
}
}
self.inspect = inspect;
}
/// If there are multiple ways to prove a trait or projection goal, we have

View File

@ -176,7 +176,8 @@ fn to_selection<'tcx>(
| ProbeKind::UnsizeAssembly
| ProbeKind::UpcastProjectionCompatibility
| ProbeKind::OpaqueTypeStorageLookup { result: _ }
| ProbeKind::Root { result: _ } => {
| ProbeKind::Root { result: _ }
| ProbeKind::ShadowedEnvProbing => {
span_bug!(span, "didn't expect to assemble trait candidate from {:#?}", cand.kind())
}
})

View File

@ -18,8 +18,8 @@ use rustc_middle::traits::query::NoSolution;
use rustc_middle::traits::solve::{inspect, QueryResult};
use rustc_middle::traits::solve::{Certainty, Goal};
use rustc_middle::traits::ObligationCause;
use rustc_middle::ty;
use rustc_middle::ty::TypeFoldable;
use rustc_middle::{bug, ty};
use rustc_span::{Span, DUMMY_SP};
use crate::solve::eval_ctxt::canonical;
@ -290,12 +290,25 @@ impl<'a, 'tcx> InspectGoal<'a, 'tcx> {
match *step {
inspect::ProbeStep::AddGoal(source, goal) => nested_goals.push((source, goal)),
inspect::ProbeStep::NestedProbe(ref probe) => {
// Nested probes have to prove goals added in their parent
// but do not leak them, so we truncate the added goals
// afterwards.
let num_goals = nested_goals.len();
self.candidates_recur(candidates, nested_goals, probe);
nested_goals.truncate(num_goals);
match probe.kind {
// These never assemble candidates for the goal we're trying to solve.
inspect::ProbeKind::UpcastProjectionCompatibility
| inspect::ProbeKind::ShadowedEnvProbing => continue,
inspect::ProbeKind::NormalizedSelfTyAssembly
| inspect::ProbeKind::UnsizeAssembly
| inspect::ProbeKind::Root { .. }
| inspect::ProbeKind::TryNormalizeNonRigid { .. }
| inspect::ProbeKind::TraitCandidate { .. }
| inspect::ProbeKind::OpaqueTypeStorageLookup { .. } => {
// Nested probes have to prove goals added in their parent
// but do not leak them, so we truncate the added goals
// afterwards.
let num_goals = nested_goals.len();
self.candidates_recur(candidates, nested_goals, probe);
nested_goals.truncate(num_goals);
}
}
}
inspect::ProbeStep::MakeCanonicalResponse { shallow_certainty: c } => {
assert_eq!(shallow_certainty.replace(c), None);
@ -308,9 +321,10 @@ impl<'a, 'tcx> InspectGoal<'a, 'tcx> {
}
match probe.kind {
inspect::ProbeKind::NormalizedSelfTyAssembly
| inspect::ProbeKind::UnsizeAssembly
| inspect::ProbeKind::UpcastProjectionCompatibility => (),
inspect::ProbeKind::UpcastProjectionCompatibility
| inspect::ProbeKind::ShadowedEnvProbing => bug!(),
inspect::ProbeKind::NormalizedSelfTyAssembly | inspect::ProbeKind::UnsizeAssembly => {}
// We add a candidate even for the root evaluation if there
// is only one way to prove a given goal, e.g. for `WellFormed`.

View File

@ -2,6 +2,7 @@
use rustc_data_structures::stable_hasher::{HashStable, StableHasher};
#[cfg(feature = "nightly")]
use rustc_macros::{HashStable_NoContext, TyDecodable, TyEncodable};
use rustc_type_ir_macros::{Lift_Generic, TypeFoldable_Generic, TypeVisitable_Generic};
use std::fmt;
use crate::{DebruijnIndex, DebugWithInfcx, InferCtxtLike, Interner, WithInfcx};
@ -86,6 +87,46 @@ impl<I: Interner> DebugWithInfcx<I> for ConstKind<I> {
}
}
/// An unevaluated (potentially generic) constant used in the type-system.
#[derive(derivative::Derivative)]
#[derivative(
Clone(bound = ""),
Copy(bound = ""),
Hash(bound = ""),
PartialEq(bound = ""),
Eq(bound = "")
)]
#[derive(TypeVisitable_Generic, TypeFoldable_Generic, Lift_Generic)]
#[cfg_attr(feature = "nightly", derive(TyDecodable, TyEncodable, HashStable_NoContext))]
pub struct UnevaluatedConst<I: Interner> {
pub def: I::DefId,
pub args: I::GenericArgs,
}
impl<I: Interner> UnevaluatedConst<I> {
#[inline]
pub fn new(def: I::DefId, args: I::GenericArgs) -> UnevaluatedConst<I> {
UnevaluatedConst { def, args }
}
}
impl<I: Interner> fmt::Debug for UnevaluatedConst<I> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
WithInfcx::with_no_infcx(self).fmt(f)
}
}
impl<I: Interner> DebugWithInfcx<I> for UnevaluatedConst<I> {
fn fmt<Infcx: InferCtxtLike<Interner = I>>(
this: WithInfcx<'_, Infcx, &Self>,
f: &mut core::fmt::Formatter<'_>,
) -> core::fmt::Result {
f.debug_struct("UnevaluatedConst")
.field("def", &this.data.def)
.field("args", &this.wrap(this.data.args))
.finish()
}
}
rustc_index::newtype_index! {
/// A **`const`** **v**ariable **ID**.
#[encodable]

View File

@ -5,7 +5,8 @@ use std::ops::Deref;
use crate::fold::TypeSuperFoldable;
use crate::visit::{Flags, TypeSuperVisitable};
use crate::{
BoundVar, ConstKind, DebruijnIndex, DebugWithInfcx, Interner, RegionKind, TyKind, UniverseIndex,
AliasTy, AliasTyKind, BoundVar, ConstKind, DebruijnIndex, DebugWithInfcx, Interner, RegionKind,
TyKind, UnevaluatedConst, UniverseIndex,
};
pub trait Ty<I: Interner<Ty = Self>>:
@ -14,12 +15,15 @@ pub trait Ty<I: Interner<Ty = Self>>:
+ Hash
+ Eq
+ Into<I::GenericArg>
+ Into<I::Term>
+ IntoKind<Kind = TyKind<I>>
+ TypeSuperVisitable<I>
+ TypeSuperFoldable<I>
+ Flags
{
fn new_anon_bound(interner: I, debruijn: DebruijnIndex, var: BoundVar) -> Self;
fn new_alias(interner: I, kind: AliasTyKind, alias_ty: AliasTy<I>) -> Self;
}
pub trait Region<I: Interner<Region = Self>>:
@ -36,6 +40,7 @@ pub trait Const<I: Interner<Const = Self>>:
+ Hash
+ Eq
+ Into<I::GenericArg>
+ Into<I::Term>
+ IntoKind<Kind = ConstKind<I>>
+ TypeSuperVisitable<I>
+ TypeSuperFoldable<I>
@ -43,6 +48,8 @@ pub trait Const<I: Interner<Const = Self>>:
{
fn new_anon_bound(interner: I, debruijn: DebruijnIndex, var: BoundVar, ty: I::Ty) -> Self;
fn new_unevaluated(interner: I, uv: UnevaluatedConst<I>, ty: I::Ty) -> Self;
fn ty(self) -> I::Ty;
}
@ -89,21 +96,3 @@ pub trait BoundVars<I: Interner> {
fn has_no_bound_vars(&self) -> bool;
}
pub trait AliasTerm<I: Interner>: Copy + DebugWithInfcx<I> + Hash + Eq + Sized {
fn new(
interner: I,
trait_def_id: I::DefId,
args: impl IntoIterator<Item: Into<I::GenericArg>>,
) -> Self;
fn def_id(self) -> I::DefId;
fn args(self) -> I::GenericArgs;
fn trait_def_id(self, interner: I) -> I::DefId;
fn self_ty(self) -> I::Ty;
fn with_self_ty(self, tcx: I, self_ty: I::Ty) -> Self;
}

View File

@ -6,13 +6,16 @@ use crate::inherent::*;
use crate::ir_print::IrPrint;
use crate::visit::{Flags, TypeSuperVisitable, TypeVisitable};
use crate::{
CanonicalVarInfo, CoercePredicate, DebugWithInfcx, ExistentialProjection, ExistentialTraitRef,
NormalizesTo, ProjectionPredicate, SubtypePredicate, TraitPredicate, TraitRef,
AliasTerm, AliasTermKind, AliasTy, AliasTyKind, CanonicalVarInfo, CoercePredicate,
DebugWithInfcx, ExistentialProjection, ExistentialTraitRef, NormalizesTo, ProjectionPredicate,
SubtypePredicate, TraitPredicate, TraitRef,
};
pub trait Interner:
Sized
+ Copy
+ IrPrint<AliasTy<Self>>
+ IrPrint<AliasTerm<Self>>
+ IrPrint<TraitRef<Self>>
+ IrPrint<TraitPredicate<Self>>
+ IrPrint<ExistentialTraitRef<Self>>
@ -27,6 +30,7 @@ pub trait Interner:
type AdtDef: Copy + Debug + Hash + Eq;
type GenericArgs: GenericArgs<Self>;
type GenericArgsSlice: Copy + Debug + Hash + Eq;
type GenericArg: Copy + DebugWithInfcx<Self> + Hash + Eq;
type Term: Copy + Debug + Hash + Eq;
@ -39,7 +43,6 @@ pub trait Interner:
// Kinds of tys
type Ty: Ty<Self>;
type Tys: Copy + Debug + Hash + Eq + IntoIterator<Item = Self::Ty>;
type AliasTy: Copy + DebugWithInfcx<Self> + Hash + Eq + Sized;
type ParamTy: Copy + Debug + Hash + Eq;
type BoundTy: Copy + Debug + Hash + Eq;
type PlaceholderTy: PlaceholderLike;
@ -74,7 +77,6 @@ pub trait Interner:
type RegionOutlivesPredicate: Copy + Debug + Hash + Eq;
type TypeOutlivesPredicate: Copy + Debug + Hash + Eq;
type ProjectionPredicate: Copy + Debug + Hash + Eq;
type AliasTerm: AliasTerm<Self>;
type NormalizesTo: Copy + Debug + Hash + Eq;
type SubtypePredicate: Copy + Debug + Hash + Eq;
type CoercePredicate: Copy + Debug + Hash + Eq;
@ -86,8 +88,23 @@ pub trait Interner:
type GenericsOf: GenericsOf<Self>;
fn generics_of(self, def_id: Self::DefId) -> Self::GenericsOf;
// FIXME: Remove after uplifting `EarlyBinder`
fn type_of_instantiated(self, def_id: Self::DefId, args: Self::GenericArgs) -> Self::Ty;
fn alias_ty_kind(self, alias: AliasTy<Self>) -> AliasTyKind;
fn alias_term_kind(self, alias: AliasTerm<Self>) -> AliasTermKind;
fn trait_ref_and_own_args_for_alias(
self,
def_id: Self::DefId,
args: Self::GenericArgs,
) -> (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 check_and_mk_args(
self,
def_id: Self::DefId,

View File

@ -1,8 +1,8 @@
use std::fmt;
use crate::{
CoercePredicate, ExistentialProjection, ExistentialTraitRef, Interner, NormalizesTo,
ProjectionPredicate, SubtypePredicate, TraitPredicate, TraitRef,
AliasTerm, AliasTy, CoercePredicate, ExistentialProjection, ExistentialTraitRef, Interner,
NormalizesTo, ProjectionPredicate, SubtypePredicate, TraitPredicate, TraitRef,
};
pub trait IrPrint<T> {
@ -43,6 +43,8 @@ define_display_via_print!(
NormalizesTo,
SubtypePredicate,
CoercePredicate,
AliasTy,
AliasTerm,
);
define_debug_via_print!(TraitRef, ExistentialTraitRef, ExistentialProjection);

View File

@ -6,7 +6,9 @@ use rustc_type_ir_macros::{Lift_Generic, TypeFoldable_Generic, TypeVisitable_Gen
use crate::inherent::*;
use crate::visit::TypeVisitableExt as _;
use crate::{DebugWithInfcx, Interner};
use crate::{
AliasTy, AliasTyKind, DebugWithInfcx, InferCtxtLike, Interner, UnevaluatedConst, WithInfcx,
};
/// A complete reference to a trait. These take numerous guises in syntax,
/// but perhaps the most recognizable form is in a where-clause:
@ -272,20 +274,20 @@ impl<I: Interner> ExistentialProjection<I> {
/// For example, if this is a projection of `exists T. <T as Iterator>::Item == X`,
/// then this function would return an `exists T. T: Iterator` existential trait
/// reference.
pub fn trait_ref(&self, tcx: I) -> ExistentialTraitRef<I> {
let def_id = tcx.parent(self.def_id);
let args_count = tcx.generics_of(def_id).count() - 1;
let args = tcx.mk_args(&self.args[..args_count]);
pub fn trait_ref(&self, interner: I) -> ExistentialTraitRef<I> {
let def_id = interner.parent(self.def_id);
let args_count = interner.generics_of(def_id).count() - 1;
let args = interner.mk_args(&self.args[..args_count]);
ExistentialTraitRef { def_id, args }
}
pub fn with_self_ty(&self, tcx: I, self_ty: I::Ty) -> ProjectionPredicate<I> {
pub fn with_self_ty(&self, interner: I, self_ty: I::Ty) -> ProjectionPredicate<I> {
// otherwise the escaping regions would be captured by the binders
debug_assert!(!self_ty.has_escaping_bound_vars());
ProjectionPredicate {
projection_term: I::AliasTerm::new(
tcx,
projection_term: AliasTerm::new(
interner,
self.def_id,
[self_ty.into()].into_iter().chain(self.args),
),
@ -293,13 +295,13 @@ impl<I: Interner> ExistentialProjection<I> {
}
}
pub fn erase_self_ty(tcx: I, projection_predicate: ProjectionPredicate<I>) -> Self {
pub fn erase_self_ty(interner: I, projection_predicate: ProjectionPredicate<I>) -> Self {
// Assert there is a Self.
projection_predicate.projection_term.args().type_at(0);
projection_predicate.projection_term.args.type_at(0);
Self {
def_id: projection_predicate.projection_term.def_id(),
args: tcx.mk_args(&projection_predicate.projection_term.args()[1..]),
def_id: projection_predicate.projection_term.def_id,
args: interner.mk_args(&projection_predicate.projection_term.args[1..]),
term: projection_predicate.term,
}
}
@ -339,6 +341,190 @@ impl AliasTermKind {
}
}
/// Represents the unprojected term of a projection goal.
///
/// * For a projection, this would be `<Ty as Trait<...>>::N<...>`.
/// * For an inherent projection, this would be `Ty::N<...>`.
/// * For an opaque type, there is no explicit syntax.
#[derive(derivative::Derivative)]
#[derivative(
Clone(bound = ""),
Copy(bound = ""),
Hash(bound = ""),
PartialEq(bound = ""),
Eq(bound = "")
)]
#[derive(TypeVisitable_Generic, TypeFoldable_Generic, Lift_Generic)]
#[cfg_attr(feature = "nightly", derive(TyDecodable, TyEncodable, HashStable_NoContext))]
pub struct AliasTerm<I: Interner> {
/// The parameters of the associated or opaque item.
///
/// For a projection, these are the generic parameters for the trait and the
/// GAT parameters, if there are any.
///
/// For an inherent projection, they consist of the self type and the GAT parameters,
/// if there are any.
///
/// For RPIT the generic parameters are for the generics of the function,
/// while for TAIT it is used for the generic parameters of the alias.
pub args: I::GenericArgs,
/// The `DefId` of the `TraitItem` or `ImplItem` for the associated type `N` depending on whether
/// this is a projection or an inherent projection or the `DefId` of the `OpaqueType` item if
/// this is an opaque.
///
/// During codegen, `interner.type_of(def_id)` can be used to get the type of the
/// underlying type if the type is an opaque.
///
/// Note that if this is an associated type, this is not the `DefId` of the
/// `TraitRef` containing this associated type, which is in `interner.associated_item(def_id).container`,
/// aka. `interner.parent(def_id)`.
pub def_id: I::DefId,
/// This field exists to prevent the creation of `AliasTerm` without using
/// [AliasTerm::new].
_use_alias_term_new_instead: (),
}
impl<I: Interner> std::fmt::Debug for AliasTerm<I> {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
WithInfcx::with_no_infcx(self).fmt(f)
}
}
impl<I: Interner> DebugWithInfcx<I> for AliasTerm<I> {
fn fmt<Infcx: InferCtxtLike<Interner = I>>(
this: WithInfcx<'_, Infcx, &Self>,
f: &mut std::fmt::Formatter<'_>,
) -> std::fmt::Result {
f.debug_struct("AliasTerm")
.field("args", &this.map(|data| data.args))
.field("def_id", &this.data.def_id)
.finish()
}
}
impl<I: Interner> AliasTerm<I> {
pub fn new(
interner: I,
def_id: I::DefId,
args: impl IntoIterator<Item: Into<I::GenericArg>>,
) -> AliasTerm<I> {
let args = interner.check_and_mk_args(def_id, args);
AliasTerm { def_id, args, _use_alias_term_new_instead: () }
}
pub fn expect_ty(self, interner: I) -> AliasTy<I> {
match self.kind(interner) {
AliasTermKind::ProjectionTy
| AliasTermKind::InherentTy
| AliasTermKind::OpaqueTy
| AliasTermKind::WeakTy => {}
AliasTermKind::UnevaluatedConst | AliasTermKind::ProjectionConst => {
panic!("Cannot turn `UnevaluatedConst` into `AliasTy`")
}
}
AliasTy { def_id: self.def_id, args: self.args, _use_alias_ty_new_instead: () }
}
pub fn kind(self, interner: I) -> AliasTermKind {
interner.alias_term_kind(self)
}
pub fn to_term(self, interner: I) -> I::Term {
match self.kind(interner) {
AliasTermKind::ProjectionTy => Ty::new_alias(
interner,
AliasTyKind::Projection,
AliasTy { def_id: self.def_id, args: self.args, _use_alias_ty_new_instead: () },
)
.into(),
AliasTermKind::InherentTy => Ty::new_alias(
interner,
AliasTyKind::Inherent,
AliasTy { def_id: self.def_id, args: self.args, _use_alias_ty_new_instead: () },
)
.into(),
AliasTermKind::OpaqueTy => Ty::new_alias(
interner,
AliasTyKind::Opaque,
AliasTy { def_id: self.def_id, args: self.args, _use_alias_ty_new_instead: () },
)
.into(),
AliasTermKind::WeakTy => Ty::new_alias(
interner,
AliasTyKind::Weak,
AliasTy { def_id: self.def_id, args: self.args, _use_alias_ty_new_instead: () },
)
.into(),
AliasTermKind::UnevaluatedConst | AliasTermKind::ProjectionConst => {
I::Const::new_unevaluated(
interner,
UnevaluatedConst::new(self.def_id, self.args),
interner.type_of_instantiated(self.def_id, self.args),
)
.into()
}
}
}
}
/// The following methods work only with (trait) associated type projections.
impl<I: Interner> AliasTerm<I> {
pub fn self_ty(self) -> I::Ty {
self.args.type_at(0)
}
pub fn with_self_ty(self, interner: I, self_ty: I::Ty) -> Self {
AliasTerm::new(
interner,
self.def_id,
[self_ty.into()].into_iter().chain(self.args.into_iter().skip(1)),
)
}
pub fn trait_def_id(self, interner: I) -> I::DefId {
assert!(
matches!(
self.kind(interner),
AliasTermKind::ProjectionTy | AliasTermKind::ProjectionConst
),
"expected a projection"
);
interner.parent(self.def_id)
}
/// Extracts the underlying trait reference and own args from this projection.
/// For example, if this is a projection of `<T as StreamingIterator>::Item<'a>`,
/// then this function would return a `T: StreamingIterator` trait reference and
/// `['a]` as the own args.
pub fn trait_ref_and_own_args(self, interner: I) -> (TraitRef<I>, I::GenericArgsSlice) {
interner.trait_ref_and_own_args_for_alias(self.def_id, self.args)
}
/// Extracts the underlying trait reference from this projection.
/// For example, if this is a projection of `<T as Iterator>::Item`,
/// then this function would return a `T: Iterator` trait reference.
///
/// WARNING: This will drop the args for generic associated types
/// consider calling [Self::trait_ref_and_own_args] to get those
/// as well.
pub fn trait_ref(self, interner: I) -> TraitRef<I> {
self.trait_ref_and_own_args(interner).0
}
}
impl<I: Interner> From<AliasTy<I>> for AliasTerm<I> {
fn from(ty: AliasTy<I>) -> Self {
AliasTerm { args: ty.args, def_id: ty.def_id, _use_alias_term_new_instead: () }
}
}
impl<I: Interner> From<UnevaluatedConst<I>> for AliasTerm<I> {
fn from(ct: UnevaluatedConst<I>) -> Self {
AliasTerm { args: ct.args, def_id: ct.def, _use_alias_term_new_instead: () }
}
}
/// This kind of predicate has no *direct* correspondent in the
/// syntax, but it roughly corresponds to the syntactic forms:
///
@ -362,7 +548,7 @@ impl AliasTermKind {
#[derive(TypeVisitable_Generic, TypeFoldable_Generic, Lift_Generic)]
#[cfg_attr(feature = "nightly", derive(TyDecodable, TyEncodable, HashStable_NoContext))]
pub struct ProjectionPredicate<I: Interner> {
pub projection_term: I::AliasTerm,
pub projection_term: AliasTerm<I>,
pub term: I::Term,
}
@ -371,16 +557,16 @@ impl<I: Interner> ProjectionPredicate<I> {
self.projection_term.self_ty()
}
pub fn with_self_ty(self, tcx: I, self_ty: I::Ty) -> ProjectionPredicate<I> {
Self { projection_term: self.projection_term.with_self_ty(tcx, self_ty), ..self }
pub fn with_self_ty(self, interner: I, self_ty: I::Ty) -> ProjectionPredicate<I> {
Self { projection_term: self.projection_term.with_self_ty(interner, self_ty), ..self }
}
pub fn trait_def_id(self, tcx: I) -> I::DefId {
self.projection_term.trait_def_id(tcx)
pub fn trait_def_id(self, interner: I) -> I::DefId {
self.projection_term.trait_def_id(interner)
}
pub fn def_id(self) -> I::DefId {
self.projection_term.def_id()
self.projection_term.def_id
}
}
@ -403,7 +589,7 @@ impl<I: Interner> fmt::Debug for ProjectionPredicate<I> {
#[derive(TypeVisitable_Generic, TypeFoldable_Generic, Lift_Generic)]
#[cfg_attr(feature = "nightly", derive(TyDecodable, TyEncodable, HashStable_NoContext))]
pub struct NormalizesTo<I: Interner> {
pub alias: I::AliasTerm,
pub alias: AliasTerm<I>,
pub term: I::Term,
}
@ -412,16 +598,16 @@ impl<I: Interner> NormalizesTo<I> {
self.alias.self_ty()
}
pub fn with_self_ty(self, tcx: I, self_ty: I::Ty) -> NormalizesTo<I> {
Self { alias: self.alias.with_self_ty(tcx, self_ty), ..self }
pub fn with_self_ty(self, interner: I, self_ty: I::Ty) -> NormalizesTo<I> {
Self { alias: self.alias.with_self_ty(interner, self_ty), ..self }
}
pub fn trait_def_id(self, tcx: I) -> I::DefId {
self.alias.trait_def_id(tcx)
pub fn trait_def_id(self, interner: I) -> I::DefId {
self.alias.trait_def_id(interner)
}
pub fn def_id(self) -> I::DefId {
self.alias.def_id()
self.alias.def_id
}
}

View File

@ -4,11 +4,11 @@ use rustc_data_structures::stable_hasher::{HashStable, StableHasher};
use rustc_data_structures::unify::{EqUnifyValue, UnifyKey};
#[cfg(feature = "nightly")]
use rustc_macros::{Decodable, Encodable, HashStable_NoContext, TyDecodable, TyEncodable};
use rustc_type_ir_macros::{TypeFoldable_Generic, TypeVisitable_Generic};
use rustc_type_ir_macros::{Lift_Generic, TypeFoldable_Generic, TypeVisitable_Generic};
use std::fmt;
use crate::Interner;
use crate::{DebruijnIndex, DebugWithInfcx, InferCtxtLike, WithInfcx};
use crate::inherent::*;
use crate::{DebruijnIndex, DebugWithInfcx, InferCtxtLike, Interner, TraitRef, WithInfcx};
use self::TyKind::*;
@ -88,7 +88,7 @@ pub enum TyKind<I: Interner> {
/// for `struct List<T>` and the args `[i32]`.
///
/// Note that generic parameters in fields only get lazily instantiated
/// by using something like `adt_def.all_fields().map(|field| field.ty(tcx, args))`.
/// by using something like `adt_def.all_fields().map(|field| field.ty(interner, args))`.
Adt(I::AdtDef, I::GenericArgs),
/// An unsized FFI type that is opaque to Rust. Written as `extern type T`.
@ -201,7 +201,7 @@ pub enum TyKind<I: Interner> {
/// A projection, opaque type, weak type alias, or inherent associated type.
/// All of these types are represented as pairs of def-id and args, and can
/// be normalized, so they are grouped conceptually.
Alias(AliasTyKind, I::AliasTy),
Alias(AliasTyKind, AliasTy<I>),
/// A type parameter; for example, `T` in `fn f<T>(x: T) {}`.
Param(I::ParamTy),
@ -422,6 +422,154 @@ impl<I: Interner> fmt::Debug for TyKind<I> {
}
}
/// Represents the projection of an associated, opaque, or lazy-type-alias type.
///
/// * For a projection, this would be `<Ty as Trait<...>>::N<...>`.
/// * For an inherent projection, this would be `Ty::N<...>`.
/// * For an opaque type, there is no explicit syntax.
#[derive(derivative::Derivative)]
#[derivative(
Clone(bound = ""),
Copy(bound = ""),
Hash(bound = ""),
PartialEq(bound = ""),
Eq(bound = "")
)]
#[derive(TypeVisitable_Generic, TypeFoldable_Generic, Lift_Generic)]
#[cfg_attr(feature = "nightly", derive(TyDecodable, TyEncodable, HashStable_NoContext))]
pub struct AliasTy<I: Interner> {
/// The parameters of the associated or opaque type.
///
/// For a projection, these are the generic parameters for the trait and the
/// GAT parameters, if there are any.
///
/// For an inherent projection, they consist of the self type and the GAT parameters,
/// if there are any.
///
/// For RPIT the generic parameters are for the generics of the function,
/// while for TAIT it is used for the generic parameters of the alias.
pub args: I::GenericArgs,
/// The `DefId` of the `TraitItem` or `ImplItem` for the associated type `N` depending on whether
/// this is a projection or an inherent projection or the `DefId` of the `OpaqueType` item if
/// this is an opaque.
///
/// During codegen, `interner.type_of(def_id)` can be used to get the type of the
/// underlying type if the type is an opaque.
///
/// Note that if this is an associated type, this is not the `DefId` of the
/// `TraitRef` containing this associated type, which is in `interner.associated_item(def_id).container`,
/// aka. `interner.parent(def_id)`.
pub def_id: I::DefId,
/// This field exists to prevent the creation of `AliasTy` without using
/// [AliasTy::new].
pub(crate) _use_alias_ty_new_instead: (),
}
impl<I: Interner> AliasTy<I> {
pub fn new(
interner: I,
def_id: I::DefId,
args: impl IntoIterator<Item: Into<I::GenericArg>>,
) -> AliasTy<I> {
let args = interner.check_and_mk_args(def_id, args);
AliasTy { def_id, args, _use_alias_ty_new_instead: () }
}
pub fn kind(self, interner: I) -> AliasTyKind {
interner.alias_ty_kind(self)
}
/// Whether this alias type is an opaque.
pub fn is_opaque(self, interner: I) -> bool {
matches!(self.kind(interner), AliasTyKind::Opaque)
}
pub fn to_ty(self, interner: I) -> I::Ty {
Ty::new_alias(interner, self.kind(interner), self)
}
}
/// The following methods work only with (trait) associated type projections.
impl<I: Interner> AliasTy<I> {
pub fn self_ty(self) -> I::Ty {
self.args.type_at(0)
}
pub fn with_self_ty(self, interner: I, self_ty: I::Ty) -> Self {
AliasTy::new(
interner,
self.def_id,
[self_ty.into()].into_iter().chain(self.args.into_iter().skip(1)),
)
}
pub fn trait_def_id(self, interner: I) -> I::DefId {
assert_eq!(self.kind(interner), AliasTyKind::Projection, "expected a projection");
interner.parent(self.def_id)
}
/// Extracts the underlying trait reference and own args from this projection.
/// For example, if this is a projection of `<T as StreamingIterator>::Item<'a>`,
/// then this function would return a `T: StreamingIterator` trait reference and
/// `['a]` as the own args.
pub fn trait_ref_and_own_args(self, interner: I) -> (TraitRef<I>, I::GenericArgsSlice) {
debug_assert_eq!(self.kind(interner), AliasTyKind::Projection);
interner.trait_ref_and_own_args_for_alias(self.def_id, self.args)
}
/// Extracts the underlying trait reference from this projection.
/// For example, if this is a projection of `<T as Iterator>::Item`,
/// then this function would return a `T: Iterator` trait reference.
///
/// WARNING: This will drop the args for generic associated types
/// consider calling [Self::trait_ref_and_own_args] to get those
/// as well.
pub fn trait_ref(self, interner: I) -> TraitRef<I> {
self.trait_ref_and_own_args(interner).0
}
}
/// The following methods work only with inherent associated type projections.
impl<I: Interner> AliasTy<I> {
/// Transform the generic parameters to have the given `impl` args as the base and the GAT args on top of that.
///
/// Does the following transformation:
///
/// ```text
/// [Self, P_0...P_m] -> [I_0...I_n, P_0...P_m]
///
/// I_i impl args
/// P_j GAT args
/// ```
pub fn rebase_inherent_args_onto_impl(
self,
impl_args: I::GenericArgs,
interner: I,
) -> I::GenericArgs {
debug_assert_eq!(self.kind(interner), AliasTyKind::Inherent);
interner.mk_args_from_iter(impl_args.into_iter().chain(self.args.into_iter().skip(1)))
}
}
impl<I: Interner> fmt::Debug for AliasTy<I> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
WithInfcx::with_no_infcx(self).fmt(f)
}
}
impl<I: Interner> DebugWithInfcx<I> for AliasTy<I> {
fn fmt<Infcx: InferCtxtLike<Interner = I>>(
this: WithInfcx<'_, Infcx, &Self>,
f: &mut core::fmt::Formatter<'_>,
) -> core::fmt::Result {
f.debug_struct("AliasTy")
.field("args", &this.map(|data| data.args))
.field("def_id", &this.data.def_id)
.finish()
}
}
#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
#[cfg_attr(feature = "nightly", derive(Encodable, Decodable, HashStable_NoContext))]
pub enum IntTy {

View File

@ -40,6 +40,8 @@ include:
of a delimited expression, delimited expressions are generally combinable,
regardless of the number of members. Previously only applied with exactly
one member (except for closures with explicit blocks).
- When line-breaking a binary operator, if the first operand spans multiple
lines, use the base indentation of the last line.
- Miscellaneous `rustfmt` bugfixes.
- Use version-sort (sort `x8`, `x16`, `x32`, `x64`, `x128` in that order).
- Change "ASCIIbetical" sort to Unicode-aware "non-lowercase before lowercase".

View File

@ -328,6 +328,37 @@ foo_bar
Prefer line-breaking at an assignment operator (either `=` or `+=`, etc.) rather
than at other binary operators.
If line-breaking at a binary operator (including assignment operators) where the
first operand spans multiple lines, use the base indentation of the *last*
line of the first operand, and indent relative to that:
```rust
impl SomeType {
fn method(&mut self) {
self.array[array_index as usize]
.as_mut()
.expect("thing must exist")
.extra_info =
long_long_long_long_long_long_long_long_long_long_long_long_long_long_long;
self.array[array_index as usize]
.as_mut()
.expect("thing must exist")
.extra_info
+ long_long_long_long_long_long_long_long_long_long_long_long_long_long_long;
self.array[array_index as usize]
.as_mut()
.expect("thing must exist")
.extra_info = Some(ExtraInfo {
parent,
count: count as u16,
children: children.into_boxed_slice(),
});
}
}
```
### Casts (`as`)
Format `as` casts like a binary operator. In particular, always include spaces

View File

@ -150,6 +150,19 @@ impl Rustc {
self
}
/// Enables link time optimizations in rustc. Equivalent to `-Clto``.
pub fn lto(&mut self) -> &mut Self {
self.cmd.arg("-Clto");
self
}
/// Add a directory to the library search path.
pub fn library_search_path<P: AsRef<Path>>(&mut self, path: P) -> &mut Self {
self.cmd.arg("-L");
self.cmd.arg(path.as_ref());
self
}
/// Specify the edition year.
pub fn edition(&mut self, edition: &str) -> &mut Self {
self.cmd.arg("--edition");

View File

@ -95,7 +95,6 @@ run-make/issue-107094/Makefile
run-make/issue-10971-temps-dir/Makefile
run-make/issue-109934-lto-debuginfo/Makefile
run-make/issue-11908/Makefile
run-make/issue-14500/Makefile
run-make/issue-14698/Makefile
run-make/issue-15460/Makefile
run-make/issue-18943/Makefile

View File

@ -26,8 +26,7 @@ fn main() {
.arg("--test")
.arg("--persist-doctests")
.arg(out_dir)
.arg("--extern")
.arg(format!("t={}", extern_path.display()))
.extern_("t", extern_path)
.run();
check_generated_binaries();
});
@ -38,8 +37,7 @@ fn main() {
.arg("--test")
.arg("--persist-doctests")
.arg(out_dir)
.arg("--extern")
.arg(format!("t={}", extern_path.display()))
.extern_("t", extern_path)
.arg("--no-run")
.run();
check_generated_binaries();
@ -59,8 +57,7 @@ fn main() {
.arg("doctests")
.arg("--test-run-directory")
.arg(run_dir)
.arg("--extern")
.arg("t=libt.rlib")
.extern_("t", "libt.rlib")
.run();
remove_dir_all(run_dir_path);

View File

@ -29,8 +29,7 @@ fn main() {
.arg(run_dir_name)
.arg("--runtool")
.arg(&run_tool_binary)
.arg("--extern")
.arg("t=libt.rlib")
.extern_("t", "libt.rlib")
.current_dir(tmp_dir())
.run();

View File

@ -1,15 +0,0 @@
include ../tools.mk
# ignore-cross-compile
# Test to make sure that reachable extern fns are always available in final
# productcs, including when LTO is used. In this test, the `foo` crate has a
# reahable symbol, and is a dependency of the `bar` crate. When the `bar` crate
# is compiled with LTO, it shouldn't strip the symbol from `foo`, and that's the
# only way that `foo.c` will successfully compile.
all:
$(RUSTC) foo.rs --crate-type=rlib
$(RUSTC) bar.rs --crate-type=staticlib -C lto -L. -o $(TMPDIR)/libbar.a
$(CC) foo.c $(TMPDIR)/libbar.a $(EXTRACFLAGS) $(call OUT_EXE,foo)
$(call RUN,foo)

View File

@ -0,0 +1,26 @@
// Test to make sure that reachable extern fns are always available in final
// productcs, including when link time optimizations (LTO) are used.
// In this test, the `foo` crate has a reahable symbol,
// and is a dependency of the `bar` crate. When the `bar` crate
// is compiled with LTO, it shouldn't strip the symbol from `foo`, and that's the
// only way that `foo.c` will successfully compile.
// See https://github.com/rust-lang/rust/issues/14500
//@ ignore-cross-compile
use run_make_support::{cc, extra_c_flags, run, rustc, static_lib, tmp_dir};
fn main() {
let libbar_path = static_lib("bar");
rustc().input("foo.rs").crate_type("rlib").run();
rustc()
.input("bar.rs")
.crate_type("staticlib")
.lto()
.library_search_path(".")
.output(&libbar_path)
.run();
cc().input("foo.c").input(libbar_path).args(&extra_c_flags()).out_exe("foo").run();
run("foo");
}

View File

@ -1,5 +1,4 @@
use run_make_support::{rustdoc, tmp_dir};
use std::process::Command;
use run_make_support::{python_command, rustdoc, tmp_dir};
fn main() {
let out_dir = tmp_dir().join("out");
@ -10,6 +9,5 @@ fn main() {
.output(&out_dir)
.run();
// FIXME (GuillaumeGomez): Port the python script to Rust as well.
let python = std::env::var("PYTHON").unwrap_or("python".into());
assert!(Command::new(python).arg("validate_json.py").arg(&out_dir).status().unwrap().success());
assert!(python_command().arg("validate_json.py").arg(&out_dir).status().unwrap().success());
}

View File

@ -0,0 +1,19 @@
// https://github.com/rust-lang/rust/issues/124946
struct Builder<const A: bool, const B: bool>;
impl<const A: bool> Builder<A, false> {
fn cast(self) -> Builder<A, true> {
Builder
}
}
impl Builder<true, true> {
fn build(self) {}
}
fn main() {
let b = Builder::<false, false>;
b.cast().build();
//~^ ERROR: no method named `build` found for struct `Builder<false, true>` in the current scope
}

View File

@ -0,0 +1,15 @@
error[E0599]: no method named `build` found for struct `Builder<false, true>` in the current scope
--> $DIR/lookup-method.rs:17:14
|
LL | struct Builder<const A: bool, const B: bool>;
| -------------------------------------------- method `build` not found for this struct
...
LL | b.cast().build();
| ^^^^^ method not found in `Builder<false, true>`
|
= note: the method was found for
- `Builder<true, true>`
error: aborting due to 1 previous error
For more information about this error, try `rustc --explain E0599`.

View File

@ -0,0 +1,163 @@
#![allow(non_snake_case)]
// Ensures that we don't spend an unnecessary amount of compiler time building
// suggestions for mistyped methods. This used to happen because when we had method
// lookup failures, we would do subsequent method lookups, and those would themselves
// do extra work that was unnecessary for the purposes of suggestions.
// Fixed by #125100.
macro_rules! traits {
($($name:ident),*) => {
$(
trait $name {
fn $name(&self);
}
)*
}
}
traits!(
A0, A1, A2, A3, A4, A5, A6, A7, A8, A9, A10, A11, A12, A13, A14, A15, A16, A17, A18, A19, A20,
A21, A22, A23, A24, A25, A26, A27, A28, A29, A30, A31, A32, A33, A34, A35, A36, A37, A38, A39,
A40, A41, A42, A43, A44, A45, A46, A47, A48, A49, A50, A51, A52, A53, A54, A55, A56, A57, A58,
A59, A60, A61, A62, A63, A64, A65, A66, A67, A68, A69, A70, A71, A72, A73, A74, A75, A76, A77,
A78, A79, A80, A81, A82, A83, A84, A85, A86, A87, A88, A89, A90, A91, A92, A93, A94, A95, A96,
A97, A98, A99, A100, A101, A102, A103, A104, A105, A106, A107, A108, A109, A110, A111, A112,
A113, A114, A115, A116, A117, A118, A119, A120, A121, A122, A123, A124, A125, A126, A127, A128,
A129, A130, A131, A132, A133, A134, A135, A136, A137, A138, A139, A140, A141, A142, A143, A144,
A145, A146, A147, A148, A149, A150, A151, A152, A153, A154, A155, A156, A157, A158, A159, A160,
A161, A162, A163, A164, A165, A166, A167, A168, A169, A170, A171, A172, A173, A174, A175, A176,
A177, A178, A179, A180, A181, A182, A183, A184, A185, A186, A187, A188, A189, A190, A191, A192,
A193, A194, A195, A196, A197, A198, A199, A200, A201, A202, A203, A204, A205, A206, A207, A208,
A209, A210, A211, A212, A213, A214, A215, A216, A217, A218, A219, A220, A221, A222, A223, A224,
A225, A226, A227, A228, A229, A230, A231, A232, A233, A234, A235, A236, A237, A238, A239, A240,
A241, A242, A243, A244, A245, A246, A247, A248, A249, A250, A251, A252, A253, A254, A255, A256,
A257, A258, A259, A260, A261, A262, A263, A264, A265, A266, A267, A268, A269, A270, A271, A272,
A273, A274, A275, A276, A277, A278, A279, A280, A281, A282, A283, A284, A285, A286, A287, A288,
A289, A290, A291, A292, A293, A294, A295, A296, A297, A298, A299, A300, A301, A302, A303, A304,
A305, A306, A307, A308, A309, A310, A311, A312, A313, A314, A315, A316, A317, A318, A319, A320,
A321, A322, A323, A324, A325, A326, A327, A328, A329, A330, A331, A332, A333, A334, A335, A336,
A337, A338, A339, A340, A341, A342, A343, A344, A345, A346, A347, A348, A349, A350, A351, A352,
A353, A354, A355, A356, A357, A358, A359, A360, A361, A362, A363, A364, A365, A366, A367, A368,
A369, A370, A371, A372, A373, A374, A375, A376, A377, A378, A379, A380, A381, A382, A383, A384,
A385, A386, A387, A388, A389, A390, A391, A392, A393, A394, A395, A396, A397, A398, A399, A400,
A401, A402, A403, A404, A405, A406, A407, A408, A409, A410, A411, A412, A413, A414, A415, A416,
A417, A418, A419, A420, A421, A422, A423, A424, A425, A426, A427, A428, A429, A430, A431, A432,
A433, A434, A435, A436, A437, A438, A439, A440, A441, A442, A443, A444, A445, A446, A447, A448,
A449, A450, A451, A452, A453, A454, A455, A456, A457, A458, A459, A460, A461, A462, A463, A464,
A465, A466, A467, A468, A469, A470, A471, A472, A473, A474, A475, A476, A477, A478, A479, A480,
A481, A482, A483, A484, A485, A486, A487, A488, A489, A490, A491, A492, A493, A494, A495, A496,
A497, A498, A499, A500, A501, A502, A503, A504, A505, A506, A507, A508, A509, A510, A511, A512,
A513, A514, A515, A516, A517, A518, A519, A520, A521, A522, A523, A524, A525, A526, A527, A528,
A529, A530, A531, A532, A533, A534, A535, A536, A537, A538, A539, A540, A541, A542, A543, A544,
A545, A546, A547, A548, A549, A550, A551, A552, A553, A554, A555, A556, A557, A558, A559, A560,
A561, A562, A563, A564, A565, A566, A567, A568, A569, A570, A571, A572, A573, A574, A575, A576,
A577, A578, A579, A580, A581, A582, A583, A584, A585, A586, A587, A588, A589, A590, A591, A592,
A593, A594, A595, A596, A597, A598, A599, A600, A601, A602, A603, A604, A605, A606, A607, A608,
A609, A610, A611, A612, A613, A614, A615, A616, A617, A618, A619, A620, A621, A622, A623, A624,
A625, A626, A627, A628, A629, A630, A631, A632, A633, A634, A635, A636, A637, A638, A639, A640,
A641, A642, A643, A644, A645, A646, A647, A648, A649, A650, A651, A652, A653, A654, A655, A656,
A657, A658, A659, A660, A661, A662, A663, A664, A665, A666, A667, A668, A669, A670, A671, A672,
A673, A674, A675, A676, A677, A678, A679, A680, A681, A682, A683, A684, A685, A686, A687, A688,
A689, A690, A691, A692, A693, A694, A695, A696, A697, A698, A699, A700, A701, A702, A703, A704,
A705, A706, A707, A708, A709, A710, A711, A712, A713, A714, A715, A716, A717, A718, A719, A720,
A721, A722, A723, A724, A725, A726, A727, A728, A729, A730, A731, A732, A733, A734, A735, A736,
A737, A738, A739, A740, A741, A742, A743, A744, A745, A746, A747, A748, A749, A750, A751, A752,
A753, A754, A755, A756, A757, A758, A759, A760, A761, A762, A763, A764, A765, A766, A767, A768,
A769, A770, A771, A772, A773, A774, A775, A776, A777, A778, A779, A780, A781, A782, A783, A784,
A785, A786, A787, A788, A789, A790, A791, A792, A793, A794, A795, A796, A797, A798, A799, A800,
A801, A802, A803, A804, A805, A806, A807, A808, A809, A810, A811, A812, A813, A814, A815, A816,
A817, A818, A819, A820, A821, A822, A823, A824, A825, A826, A827, A828, A829, A830, A831, A832,
A833, A834, A835, A836, A837, A838, A839, A840, A841, A842, A843, A844, A845, A846, A847, A848,
A849, A850, A851, A852, A853, A854, A855, A856, A857, A858, A859, A860, A861, A862, A863, A864,
A865, A866, A867, A868, A869, A870, A871, A872, A873, A874, A875, A876, A877, A878, A879, A880,
A881, A882, A883, A884, A885, A886, A887, A888, A889, A890, A891, A892, A893, A894, A895, A896,
A897, A898, A899, A900, A901, A902, A903, A904, A905, A906, A907, A908, A909, A910, A911, A912,
A913, A914, A915, A916, A917, A918, A919, A920, A921, A922, A923, A924, A925, A926, A927, A928,
A929, A930, A931, A932, A933, A934, A935, A936, A937, A938, A939, A940, A941, A942, A943, A944,
A945, A946, A947, A948, A949, A950, A951, A952, A953, A954, A955, A956, A957, A958, A959, A960,
A961, A962, A963, A964, A965, A966, A967, A968, A969, A970, A971, A972, A973, A974, A975, A976,
A977, A978, A979, A980, A981, A982, A983, A984, A985, A986, A987, A988, A989, A990, A991, A992,
A993, A994, A995, A996, A997, A998, A999
);
#[derive(Default)]
struct M0 {
m1: M1,
m2: M1,
m3: M1,
m4: M1,
m5: M1,
m6: M1,
m7: M1,
m8: M1,
m9: M1,
m10: M1,
m11: M1,
m12: M1,
m13: M1,
m14: M1,
m15: M1,
}
#[derive(Default)]
struct M1 {
m1: M2,
m2: M2,
m3: M2,
m4: M2,
m5: M2,
m6: M2,
m7: M2,
m8: M2,
m9: M2,
m10: M2,
m11: M2,
m12: M2,
m13: M2,
m14: M2,
m15: M2,
}
#[derive(Default)]
struct M2 {
m1: M3,
m2: M3,
m3: M3,
m4: M3,
m5: M3,
m6: M3,
m7: M3,
m8: M3,
m9: M3,
m10: M3,
m11: M3,
m12: M3,
m13: M3,
m14: M3,
m15: M3,
}
#[derive(Default)]
struct M3 {}
fn main() {
M0::default().Au();
//~^ ERROR no method named `Au` found for struct `M0` in the current scope
M0::default().Au();
//~^ ERROR no method named `Au` found for struct `M0` in the current scope
M0::default().Au();
//~^ ERROR no method named `Au` found for struct `M0` in the current scope
M0::default().Au();
//~^ ERROR no method named `Au` found for struct `M0` in the current scope
M0::default().Au();
//~^ ERROR no method named `Au` found for struct `M0` in the current scope
M0::default().Au();
//~^ ERROR no method named `Au` found for struct `M0` in the current scope
M0::default().Au();
//~^ ERROR no method named `Au` found for struct `M0` in the current scope
M0::default().Au();
//~^ ERROR no method named `Au` found for struct `M0` in the current scope
M0::default().Au();
//~^ ERROR no method named `Au` found for struct `M0` in the current scope
}

View File

@ -0,0 +1,84 @@
error[E0599]: no method named `Au` found for struct `M0` in the current scope
--> $DIR/probe-for-diagnostic-doesnt-do-extra-work.rs:145:19
|
LL | struct M0 {
| --------- method `Au` not found for this struct
...
LL | M0::default().Au();
| ^^ method not found in `M0`
error[E0599]: no method named `Au` found for struct `M0` in the current scope
--> $DIR/probe-for-diagnostic-doesnt-do-extra-work.rs:147:19
|
LL | struct M0 {
| --------- method `Au` not found for this struct
...
LL | M0::default().Au();
| ^^ method not found in `M0`
error[E0599]: no method named `Au` found for struct `M0` in the current scope
--> $DIR/probe-for-diagnostic-doesnt-do-extra-work.rs:149:19
|
LL | struct M0 {
| --------- method `Au` not found for this struct
...
LL | M0::default().Au();
| ^^ method not found in `M0`
error[E0599]: no method named `Au` found for struct `M0` in the current scope
--> $DIR/probe-for-diagnostic-doesnt-do-extra-work.rs:151:19
|
LL | struct M0 {
| --------- method `Au` not found for this struct
...
LL | M0::default().Au();
| ^^ method not found in `M0`
error[E0599]: no method named `Au` found for struct `M0` in the current scope
--> $DIR/probe-for-diagnostic-doesnt-do-extra-work.rs:153:19
|
LL | struct M0 {
| --------- method `Au` not found for this struct
...
LL | M0::default().Au();
| ^^ method not found in `M0`
error[E0599]: no method named `Au` found for struct `M0` in the current scope
--> $DIR/probe-for-diagnostic-doesnt-do-extra-work.rs:155:19
|
LL | struct M0 {
| --------- method `Au` not found for this struct
...
LL | M0::default().Au();
| ^^ method not found in `M0`
error[E0599]: no method named `Au` found for struct `M0` in the current scope
--> $DIR/probe-for-diagnostic-doesnt-do-extra-work.rs:157:19
|
LL | struct M0 {
| --------- method `Au` not found for this struct
...
LL | M0::default().Au();
| ^^ method not found in `M0`
error[E0599]: no method named `Au` found for struct `M0` in the current scope
--> $DIR/probe-for-diagnostic-doesnt-do-extra-work.rs:159:19
|
LL | struct M0 {
| --------- method `Au` not found for this struct
...
LL | M0::default().Au();
| ^^ method not found in `M0`
error[E0599]: no method named `Au` found for struct `M0` in the current scope
--> $DIR/probe-for-diagnostic-doesnt-do-extra-work.rs:161:19
|
LL | struct M0 {
| --------- method `Au` not found for this struct
...
LL | M0::default().Au();
| ^^ method not found in `M0`
error: aborting due to 9 previous errors
For more information about this error, try `rustc --explain E0599`.