Auto merge of #113890 - matthiaskrgr:rollup-k1w2vii, r=matthiaskrgr
Rollup of 7 pull requests Successful merges: - #110765 (rustdoc: fix position of `default` in method rendering) - #113529 (Permit pre-evaluated constants in simd_shuffle) - #113800 (Avoid another gha group nesting) - #113827 (Add Foreign, Never, FnDef, Closure and Generator tys to SMIR) - #113835 (new solver: don't consider blanket impls multiple times) - #113883 (Remove outdated Firefox-specific CSS for search's crate selector appearance) - #113884 (Don't translate compiler-internal bug messages) r? `@ghost` `@rustbot` modify labels: rollup
This commit is contained in:
commit
092e4f46be
27 changed files with 619 additions and 286 deletions
|
@ -65,8 +65,22 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
|
|||
&self,
|
||||
constant: &mir::Constant<'tcx>,
|
||||
) -> Result<Option<ty::ValTree<'tcx>>, ErrorHandled> {
|
||||
let uv = match constant.literal {
|
||||
let uv = match self.monomorphize(constant.literal) {
|
||||
mir::ConstantKind::Unevaluated(uv, _) => uv.shrink(),
|
||||
mir::ConstantKind::Ty(c) => match c.kind() {
|
||||
// A constant that came from a const generic but was then used as an argument to old-style
|
||||
// simd_shuffle (passing as argument instead of as a generic param).
|
||||
rustc_type_ir::ConstKind::Value(valtree) => return Ok(Some(valtree)),
|
||||
other => span_bug!(constant.span, "{other:#?}"),
|
||||
},
|
||||
// We should never encounter `ConstantKind::Val` unless MIR opts (like const prop) evaluate
|
||||
// a constant and write that value back into `Operand`s. This could happen, but is unlikely.
|
||||
// Also: all users of `simd_shuffle` are on unstable and already need to take a lot of care
|
||||
// around intrinsics. For an issue to happen here, it would require a macro expanding to a
|
||||
// `simd_shuffle` call without wrapping the constant argument in a `const {}` block, but
|
||||
// the user pass through arbitrary expressions.
|
||||
// FIXME(oli-obk): replace the magic const generic argument of `simd_shuffle` with a real
|
||||
// const generic.
|
||||
other => span_bug!(constant.span, "{other:#?}"),
|
||||
};
|
||||
let uv = self.monomorphize(uv);
|
||||
|
|
|
@ -1003,7 +1003,7 @@ impl Handler {
|
|||
self.emit_diag_at_span(Diagnostic::new_with_code(Warning(None), Some(code), msg), span);
|
||||
}
|
||||
|
||||
pub fn span_bug(&self, span: impl Into<MultiSpan>, msg: impl Into<DiagnosticMessage>) -> ! {
|
||||
pub fn span_bug(&self, span: impl Into<MultiSpan>, msg: impl Into<String>) -> ! {
|
||||
self.inner.borrow_mut().span_bug(span, msg)
|
||||
}
|
||||
|
||||
|
@ -1012,7 +1012,7 @@ impl Handler {
|
|||
pub fn delay_span_bug(
|
||||
&self,
|
||||
span: impl Into<MultiSpan>,
|
||||
msg: impl Into<DiagnosticMessage>,
|
||||
msg: impl Into<String>,
|
||||
) -> ErrorGuaranteed {
|
||||
self.inner.borrow_mut().delay_span_bug(span, msg)
|
||||
}
|
||||
|
@ -1596,8 +1596,8 @@ impl HandlerInner {
|
|||
}
|
||||
|
||||
#[track_caller]
|
||||
fn span_bug(&mut self, sp: impl Into<MultiSpan>, msg: impl Into<DiagnosticMessage>) -> ! {
|
||||
self.emit_diag_at_span(Diagnostic::new(Bug, msg), sp);
|
||||
fn span_bug(&mut self, sp: impl Into<MultiSpan>, msg: impl Into<String>) -> ! {
|
||||
self.emit_diag_at_span(Diagnostic::new(Bug, msg.into()), sp);
|
||||
panic::panic_any(ExplicitBug);
|
||||
}
|
||||
|
||||
|
@ -1610,7 +1610,7 @@ impl HandlerInner {
|
|||
fn delay_span_bug(
|
||||
&mut self,
|
||||
sp: impl Into<MultiSpan>,
|
||||
msg: impl Into<DiagnosticMessage>,
|
||||
msg: impl Into<String>,
|
||||
) -> ErrorGuaranteed {
|
||||
// This is technically `self.treat_err_as_bug()` but `delay_span_bug` is called before
|
||||
// incrementing `err_count` by one, so we need to +1 the comparing.
|
||||
|
@ -1619,9 +1619,9 @@ impl HandlerInner {
|
|||
self.err_count() + self.lint_err_count + self.delayed_bug_count() + 1 >= c.get()
|
||||
}) {
|
||||
// FIXME: don't abort here if report_delayed_bugs is off
|
||||
self.span_bug(sp, msg);
|
||||
self.span_bug(sp, msg.into());
|
||||
}
|
||||
let mut diagnostic = Diagnostic::new(Level::DelayedBug, msg);
|
||||
let mut diagnostic = Diagnostic::new(Level::DelayedBug, msg.into());
|
||||
diagnostic.set_span(sp.into());
|
||||
self.emit_diagnostic(&mut diagnostic).unwrap()
|
||||
}
|
||||
|
|
|
@ -1147,7 +1147,7 @@ impl<'a> ExtCtxt<'a> {
|
|||
pub fn span_warn<S: Into<MultiSpan>>(&self, sp: S, msg: impl Into<DiagnosticMessage>) {
|
||||
self.sess.parse_sess.span_diagnostic.span_warn(sp, msg);
|
||||
}
|
||||
pub fn span_bug<S: Into<MultiSpan>>(&self, sp: S, msg: impl Into<DiagnosticMessage>) -> ! {
|
||||
pub fn span_bug<S: Into<MultiSpan>>(&self, sp: S, msg: impl Into<String>) -> ! {
|
||||
self.sess.parse_sess.span_diagnostic.span_bug(sp, msg);
|
||||
}
|
||||
pub fn trace_macros_diag(&mut self) {
|
||||
|
|
|
@ -568,10 +568,10 @@ fn fast_reject_auto_impl<'tcx>(tcx: TyCtxt<'tcx>, trait_def_id: DefId, self_ty:
|
|||
|
||||
impl<'tcx> TypeVisitor<TyCtxt<'tcx>> for DisableAutoTraitVisitor<'tcx> {
|
||||
type BreakTy = ();
|
||||
fn visit_ty(&mut self, t: Ty<'tcx>) -> ControlFlow<Self::BreakTy> {
|
||||
fn visit_ty(&mut self, ty: Ty<'tcx>) -> ControlFlow<Self::BreakTy> {
|
||||
let tcx = self.tcx;
|
||||
if t != self.self_ty_root {
|
||||
for impl_def_id in tcx.non_blanket_impls_for_ty(self.trait_def_id, t) {
|
||||
if ty != self.self_ty_root {
|
||||
for impl_def_id in tcx.non_blanket_impls_for_ty(self.trait_def_id, ty) {
|
||||
match tcx.impl_polarity(impl_def_id) {
|
||||
ImplPolarity::Negative => return ControlFlow::Break(()),
|
||||
ImplPolarity::Reservation => {}
|
||||
|
@ -584,7 +584,7 @@ fn fast_reject_auto_impl<'tcx>(tcx: TyCtxt<'tcx>, trait_def_id: DefId, self_ty:
|
|||
}
|
||||
}
|
||||
|
||||
match t.kind() {
|
||||
match ty.kind() {
|
||||
ty::Adt(def, args) if def.is_phantom_data() => args.visit_with(self),
|
||||
ty::Adt(def, args) => {
|
||||
// @lcnr: This is the only place where cycles can happen. We avoid this
|
||||
|
@ -599,7 +599,7 @@ fn fast_reject_auto_impl<'tcx>(tcx: TyCtxt<'tcx>, trait_def_id: DefId, self_ty:
|
|||
|
||||
ControlFlow::Continue(())
|
||||
}
|
||||
_ => t.super_visit_with(self),
|
||||
_ => ty.super_visit_with(self),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -6,35 +6,33 @@ use std::fmt::Debug;
|
|||
use std::hash::Hash;
|
||||
use std::iter;
|
||||
|
||||
use self::SimplifiedType::*;
|
||||
|
||||
/// See `simplify_type`.
|
||||
#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, TyEncodable, TyDecodable, HashStable)]
|
||||
pub enum SimplifiedType {
|
||||
BoolSimplifiedType,
|
||||
CharSimplifiedType,
|
||||
IntSimplifiedType(ty::IntTy),
|
||||
UintSimplifiedType(ty::UintTy),
|
||||
FloatSimplifiedType(ty::FloatTy),
|
||||
AdtSimplifiedType(DefId),
|
||||
ForeignSimplifiedType(DefId),
|
||||
StrSimplifiedType,
|
||||
ArraySimplifiedType,
|
||||
SliceSimplifiedType,
|
||||
RefSimplifiedType(Mutability),
|
||||
PtrSimplifiedType(Mutability),
|
||||
NeverSimplifiedType,
|
||||
TupleSimplifiedType(usize),
|
||||
Bool,
|
||||
Char,
|
||||
Int(ty::IntTy),
|
||||
Uint(ty::UintTy),
|
||||
Float(ty::FloatTy),
|
||||
Adt(DefId),
|
||||
Foreign(DefId),
|
||||
Str,
|
||||
Array,
|
||||
Slice,
|
||||
Ref(Mutability),
|
||||
Ptr(Mutability),
|
||||
Never,
|
||||
Tuple(usize),
|
||||
/// A trait object, all of whose components are markers
|
||||
/// (e.g., `dyn Send + Sync`).
|
||||
MarkerTraitObjectSimplifiedType,
|
||||
TraitSimplifiedType(DefId),
|
||||
ClosureSimplifiedType(DefId),
|
||||
GeneratorSimplifiedType(DefId),
|
||||
GeneratorWitnessSimplifiedType(usize),
|
||||
GeneratorWitnessMIRSimplifiedType(DefId),
|
||||
FunctionSimplifiedType(usize),
|
||||
PlaceholderSimplifiedType,
|
||||
MarkerTraitObject,
|
||||
Trait(DefId),
|
||||
Closure(DefId),
|
||||
Generator(DefId),
|
||||
GeneratorWitness(usize),
|
||||
GeneratorWitnessMIR(DefId),
|
||||
Function(usize),
|
||||
Placeholder,
|
||||
}
|
||||
|
||||
/// Generic parameters are pretty much just bound variables, e.g.
|
||||
|
@ -64,6 +62,9 @@ pub enum TreatParams {
|
|||
/// correct mode for *lookup*, as during candidate selection.
|
||||
///
|
||||
/// N.B. during deep rejection, this acts identically to `ForLookup`.
|
||||
///
|
||||
/// FIXME(-Ztrait-solver=next): Remove this variant and cleanup
|
||||
/// the code.
|
||||
NextSolverLookup,
|
||||
}
|
||||
|
||||
|
@ -110,34 +111,36 @@ pub fn simplify_type<'tcx>(
|
|||
treat_params: TreatParams,
|
||||
) -> Option<SimplifiedType> {
|
||||
match *ty.kind() {
|
||||
ty::Bool => Some(BoolSimplifiedType),
|
||||
ty::Char => Some(CharSimplifiedType),
|
||||
ty::Int(int_type) => Some(IntSimplifiedType(int_type)),
|
||||
ty::Uint(uint_type) => Some(UintSimplifiedType(uint_type)),
|
||||
ty::Float(float_type) => Some(FloatSimplifiedType(float_type)),
|
||||
ty::Adt(def, _) => Some(AdtSimplifiedType(def.did())),
|
||||
ty::Str => Some(StrSimplifiedType),
|
||||
ty::Array(..) => Some(ArraySimplifiedType),
|
||||
ty::Slice(..) => Some(SliceSimplifiedType),
|
||||
ty::RawPtr(ptr) => Some(PtrSimplifiedType(ptr.mutbl)),
|
||||
ty::Bool => Some(SimplifiedType::Bool),
|
||||
ty::Char => Some(SimplifiedType::Char),
|
||||
ty::Int(int_type) => Some(SimplifiedType::Int(int_type)),
|
||||
ty::Uint(uint_type) => Some(SimplifiedType::Uint(uint_type)),
|
||||
ty::Float(float_type) => Some(SimplifiedType::Float(float_type)),
|
||||
ty::Adt(def, _) => Some(SimplifiedType::Adt(def.did())),
|
||||
ty::Str => Some(SimplifiedType::Str),
|
||||
ty::Array(..) => Some(SimplifiedType::Array),
|
||||
ty::Slice(..) => Some(SimplifiedType::Slice),
|
||||
ty::RawPtr(ptr) => Some(SimplifiedType::Ptr(ptr.mutbl)),
|
||||
ty::Dynamic(trait_info, ..) => match trait_info.principal_def_id() {
|
||||
Some(principal_def_id) if !tcx.trait_is_auto(principal_def_id) => {
|
||||
Some(TraitSimplifiedType(principal_def_id))
|
||||
Some(SimplifiedType::Trait(principal_def_id))
|
||||
}
|
||||
_ => Some(MarkerTraitObjectSimplifiedType),
|
||||
_ => Some(SimplifiedType::MarkerTraitObject),
|
||||
},
|
||||
ty::Ref(_, _, mutbl) => Some(RefSimplifiedType(mutbl)),
|
||||
ty::FnDef(def_id, _) | ty::Closure(def_id, _) => Some(ClosureSimplifiedType(def_id)),
|
||||
ty::Generator(def_id, _, _) => Some(GeneratorSimplifiedType(def_id)),
|
||||
ty::GeneratorWitness(tys) => Some(GeneratorWitnessSimplifiedType(tys.skip_binder().len())),
|
||||
ty::GeneratorWitnessMIR(def_id, _) => Some(GeneratorWitnessMIRSimplifiedType(def_id)),
|
||||
ty::Never => Some(NeverSimplifiedType),
|
||||
ty::Tuple(tys) => Some(TupleSimplifiedType(tys.len())),
|
||||
ty::FnPtr(f) => Some(FunctionSimplifiedType(f.skip_binder().inputs().len())),
|
||||
ty::Placeholder(..) => Some(PlaceholderSimplifiedType),
|
||||
ty::Ref(_, _, mutbl) => Some(SimplifiedType::Ref(mutbl)),
|
||||
ty::FnDef(def_id, _) | ty::Closure(def_id, _) => Some(SimplifiedType::Closure(def_id)),
|
||||
ty::Generator(def_id, _, _) => Some(SimplifiedType::Generator(def_id)),
|
||||
ty::GeneratorWitness(tys) => {
|
||||
Some(SimplifiedType::GeneratorWitness(tys.skip_binder().len()))
|
||||
}
|
||||
ty::GeneratorWitnessMIR(def_id, _) => Some(SimplifiedType::GeneratorWitnessMIR(def_id)),
|
||||
ty::Never => Some(SimplifiedType::Never),
|
||||
ty::Tuple(tys) => Some(SimplifiedType::Tuple(tys.len())),
|
||||
ty::FnPtr(f) => Some(SimplifiedType::Function(f.skip_binder().inputs().len())),
|
||||
ty::Placeholder(..) => Some(SimplifiedType::Placeholder),
|
||||
ty::Param(_) => match treat_params {
|
||||
TreatParams::ForLookup | TreatParams::NextSolverLookup => {
|
||||
Some(PlaceholderSimplifiedType)
|
||||
Some(SimplifiedType::Placeholder)
|
||||
}
|
||||
TreatParams::AsCandidateKey => None,
|
||||
},
|
||||
|
@ -147,11 +150,13 @@ pub fn simplify_type<'tcx>(
|
|||
//
|
||||
// We will have to be careful with lazy normalization here.
|
||||
// FIXME(lazy_normalization): This is probably not right...
|
||||
TreatParams::ForLookup if !ty.has_non_region_infer() => Some(PlaceholderSimplifiedType),
|
||||
TreatParams::NextSolverLookup => Some(PlaceholderSimplifiedType),
|
||||
TreatParams::ForLookup if !ty.has_non_region_infer() => {
|
||||
Some(SimplifiedType::Placeholder)
|
||||
}
|
||||
TreatParams::NextSolverLookup => Some(SimplifiedType::Placeholder),
|
||||
TreatParams::ForLookup | TreatParams::AsCandidateKey => None,
|
||||
},
|
||||
ty::Foreign(def_id) => Some(ForeignSimplifiedType(def_id)),
|
||||
ty::Foreign(def_id) => Some(SimplifiedType::Foreign(def_id)),
|
||||
ty::Bound(..) | ty::Infer(_) | ty::Error(_) => None,
|
||||
}
|
||||
}
|
||||
|
@ -159,12 +164,12 @@ pub fn simplify_type<'tcx>(
|
|||
impl SimplifiedType {
|
||||
pub fn def(self) -> Option<DefId> {
|
||||
match self {
|
||||
AdtSimplifiedType(d)
|
||||
| ForeignSimplifiedType(d)
|
||||
| TraitSimplifiedType(d)
|
||||
| ClosureSimplifiedType(d)
|
||||
| GeneratorSimplifiedType(d)
|
||||
| GeneratorWitnessMIRSimplifiedType(d) => Some(d),
|
||||
SimplifiedType::Adt(d)
|
||||
| SimplifiedType::Foreign(d)
|
||||
| SimplifiedType::Trait(d)
|
||||
| SimplifiedType::Closure(d)
|
||||
| SimplifiedType::Generator(d)
|
||||
| SimplifiedType::GeneratorWitnessMIR(d) => Some(d),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
|
|
|
@ -15,7 +15,6 @@ use hir::def::DefKind;
|
|||
use polonius_engine::Atom;
|
||||
use rustc_data_structures::captures::Captures;
|
||||
use rustc_data_structures::intern::Interned;
|
||||
use rustc_error_messages::DiagnosticMessage;
|
||||
use rustc_errors::{DiagnosticArgValue, ErrorGuaranteed, IntoDiagnosticArg, MultiSpan};
|
||||
use rustc_hir as hir;
|
||||
use rustc_hir::def_id::DefId;
|
||||
|
@ -1991,7 +1990,7 @@ impl<'tcx> Ty<'tcx> {
|
|||
pub fn new_error_with_message<S: Into<MultiSpan>>(
|
||||
tcx: TyCtxt<'tcx>,
|
||||
span: S,
|
||||
msg: impl Into<DiagnosticMessage>,
|
||||
msg: impl Into<String>,
|
||||
) -> Ty<'tcx> {
|
||||
let reported = tcx.sess.delay_span_bug(span, msg);
|
||||
Ty::new(tcx, Error(reported))
|
||||
|
|
|
@ -247,7 +247,7 @@ impl<'a> Parser<'a> {
|
|||
self.sess.span_diagnostic.struct_span_err(sp, m)
|
||||
}
|
||||
|
||||
pub fn span_bug<S: Into<MultiSpan>>(&self, sp: S, m: impl Into<DiagnosticMessage>) -> ! {
|
||||
pub fn span_bug<S: Into<MultiSpan>>(&self, sp: S, m: impl Into<String>) -> ! {
|
||||
self.sess.span_diagnostic.span_bug(sp, m)
|
||||
}
|
||||
|
||||
|
|
|
@ -8,7 +8,6 @@ use crate::errors::{
|
|||
TrailingVertNotAllowed, UnexpectedLifetimeInPattern, UnexpectedVertVertBeforeFunctionParam,
|
||||
UnexpectedVertVertInPattern,
|
||||
};
|
||||
use crate::fluent_generated as fluent;
|
||||
use crate::{maybe_recover_from_interpolated_ty_qpath, maybe_whole};
|
||||
use rustc_ast::mut_visit::{noop_visit_pat, MutVisitor};
|
||||
use rustc_ast::ptr::P;
|
||||
|
@ -214,41 +213,25 @@ impl<'a> Parser<'a> {
|
|||
|
||||
if let PatKind::Or(pats) = &pat.kind {
|
||||
let span = pat.span;
|
||||
|
||||
if trailing_vert {
|
||||
// We already emitted an error and suggestion to remove the trailing vert. Don't
|
||||
// emit again.
|
||||
|
||||
// FIXME(#100717): pass `TopLevelOrPatternNotAllowed::* { sub: None }` to
|
||||
// `delay_span_bug()` instead of fluent message
|
||||
self.sess.span_diagnostic.delay_span_bug(
|
||||
span,
|
||||
match syntax_loc {
|
||||
PatternLocation::LetBinding => {
|
||||
fluent::parse_or_pattern_not_allowed_in_let_binding
|
||||
}
|
||||
PatternLocation::FunctionParameter => {
|
||||
fluent::parse_or_pattern_not_allowed_in_fn_parameters
|
||||
}
|
||||
},
|
||||
);
|
||||
let pat = pprust::pat_to_string(&pat);
|
||||
let sub = if pats.len() == 1 {
|
||||
Some(TopLevelOrPatternNotAllowedSugg::RemoveLeadingVert { span, pat })
|
||||
} else {
|
||||
let pat = pprust::pat_to_string(&pat);
|
||||
let sub = if pats.len() == 1 {
|
||||
Some(TopLevelOrPatternNotAllowedSugg::RemoveLeadingVert { span, pat })
|
||||
} else {
|
||||
Some(TopLevelOrPatternNotAllowedSugg::WrapInParens { span, pat })
|
||||
};
|
||||
Some(TopLevelOrPatternNotAllowedSugg::WrapInParens { span, pat })
|
||||
};
|
||||
|
||||
self.sess.emit_err(match syntax_loc {
|
||||
PatternLocation::LetBinding => {
|
||||
TopLevelOrPatternNotAllowed::LetBinding { span, sub }
|
||||
}
|
||||
PatternLocation::FunctionParameter => {
|
||||
TopLevelOrPatternNotAllowed::FunctionParameter { span, sub }
|
||||
}
|
||||
});
|
||||
let mut err = self.sess.create_err(match syntax_loc {
|
||||
PatternLocation::LetBinding => {
|
||||
TopLevelOrPatternNotAllowed::LetBinding { span, sub }
|
||||
}
|
||||
PatternLocation::FunctionParameter => {
|
||||
TopLevelOrPatternNotAllowed::FunctionParameter { span, sub }
|
||||
}
|
||||
});
|
||||
if trailing_vert {
|
||||
err.delay_as_bug();
|
||||
}
|
||||
err.emit();
|
||||
}
|
||||
|
||||
Ok((pat, colon))
|
||||
|
|
|
@ -677,7 +677,7 @@ impl Session {
|
|||
pub fn delay_span_bug<S: Into<MultiSpan>>(
|
||||
&self,
|
||||
sp: S,
|
||||
msg: impl Into<DiagnosticMessage>,
|
||||
msg: impl Into<String>,
|
||||
) -> ErrorGuaranteed {
|
||||
self.diagnostic().delay_span_bug(sp, msg)
|
||||
}
|
||||
|
|
|
@ -31,6 +31,22 @@ pub fn adt_def(did: DefId) -> stable_mir::ty::AdtDef {
|
|||
with_tables(|t| t.adt_def(did))
|
||||
}
|
||||
|
||||
pub fn foreign_def(did: DefId) -> stable_mir::ty::ForeignDef {
|
||||
with_tables(|t| t.foreign_def(did))
|
||||
}
|
||||
|
||||
pub fn fn_def(did: DefId) -> stable_mir::ty::FnDef {
|
||||
with_tables(|t| t.fn_def(did))
|
||||
}
|
||||
|
||||
pub fn closure_def(did: DefId) -> stable_mir::ty::ClosureDef {
|
||||
with_tables(|t| t.closure_def(did))
|
||||
}
|
||||
|
||||
pub fn generator_def(did: DefId) -> stable_mir::ty::GeneratorDef {
|
||||
with_tables(|t| t.generator_def(did))
|
||||
}
|
||||
|
||||
impl<'tcx> Tables<'tcx> {
|
||||
pub fn item_def_id(&self, item: &stable_mir::CrateItem) -> DefId {
|
||||
self.def_ids[item.0]
|
||||
|
@ -44,6 +60,22 @@ impl<'tcx> Tables<'tcx> {
|
|||
stable_mir::ty::AdtDef(self.create_def_id(did))
|
||||
}
|
||||
|
||||
pub fn foreign_def(&mut self, did: DefId) -> stable_mir::ty::ForeignDef {
|
||||
stable_mir::ty::ForeignDef(self.create_def_id(did))
|
||||
}
|
||||
|
||||
pub fn fn_def(&mut self, did: DefId) -> stable_mir::ty::FnDef {
|
||||
stable_mir::ty::FnDef(self.create_def_id(did))
|
||||
}
|
||||
|
||||
pub fn closure_def(&mut self, did: DefId) -> stable_mir::ty::ClosureDef {
|
||||
stable_mir::ty::ClosureDef(self.create_def_id(did))
|
||||
}
|
||||
|
||||
pub fn generator_def(&mut self, did: DefId) -> stable_mir::ty::GeneratorDef {
|
||||
stable_mir::ty::GeneratorDef(self.create_def_id(did))
|
||||
}
|
||||
|
||||
fn create_def_id(&mut self, did: DefId) -> stable_mir::DefId {
|
||||
// FIXME: this becomes inefficient when we have too many ids
|
||||
for (i, &d) in self.def_ids.iter().enumerate() {
|
||||
|
|
|
@ -8,8 +8,11 @@
|
|||
//! For now, we are developing everything inside `rustc`, thus, we keep this module private.
|
||||
|
||||
use crate::rustc_internal::{self, opaque};
|
||||
use crate::stable_mir::ty::{AdtSubsts, FloatTy, GenericArgKind, IntTy, RigidTy, TyKind, UintTy};
|
||||
use crate::stable_mir::ty::{
|
||||
FloatTy, GenericArgKind, GenericArgs, IntTy, Movability, RigidTy, TyKind, UintTy,
|
||||
};
|
||||
use crate::stable_mir::{self, Context};
|
||||
use rustc_hir as hir;
|
||||
use rustc_middle::mir;
|
||||
use rustc_middle::ty::{self, Ty, TyCtxt};
|
||||
use rustc_span::def_id::{CrateNum, DefId, LOCAL_CRATE};
|
||||
|
@ -94,26 +97,13 @@ impl<'tcx> Tables<'tcx> {
|
|||
ty::FloatTy::F32 => TyKind::RigidTy(RigidTy::Float(FloatTy::F32)),
|
||||
ty::FloatTy::F64 => TyKind::RigidTy(RigidTy::Float(FloatTy::F64)),
|
||||
},
|
||||
ty::Adt(adt_def, substs) => TyKind::RigidTy(RigidTy::Adt(
|
||||
ty::Adt(adt_def, generic_args) => TyKind::RigidTy(RigidTy::Adt(
|
||||
rustc_internal::adt_def(adt_def.did()),
|
||||
AdtSubsts(
|
||||
substs
|
||||
.iter()
|
||||
.map(|arg| match arg.unpack() {
|
||||
ty::GenericArgKind::Lifetime(region) => {
|
||||
GenericArgKind::Lifetime(opaque(®ion))
|
||||
}
|
||||
ty::GenericArgKind::Type(ty) => {
|
||||
GenericArgKind::Type(self.intern_ty(ty))
|
||||
}
|
||||
ty::GenericArgKind::Const(const_) => {
|
||||
GenericArgKind::Const(opaque(&const_))
|
||||
}
|
||||
})
|
||||
.collect(),
|
||||
),
|
||||
self.generic_args(generic_args),
|
||||
)),
|
||||
ty::Foreign(_) => todo!(),
|
||||
ty::Foreign(def_id) => {
|
||||
TyKind::RigidTy(RigidTy::Foreign(rustc_internal::foreign_def(*def_id)))
|
||||
}
|
||||
ty::Str => TyKind::RigidTy(RigidTy::Str),
|
||||
ty::Array(ty, constant) => {
|
||||
TyKind::RigidTy(RigidTy::Array(self.intern_ty(*ty), opaque(constant)))
|
||||
|
@ -125,12 +115,25 @@ impl<'tcx> Tables<'tcx> {
|
|||
ty::Ref(region, ty, mutbl) => {
|
||||
TyKind::RigidTy(RigidTy::Ref(opaque(region), self.intern_ty(*ty), mutbl.stable()))
|
||||
}
|
||||
ty::FnDef(_, _) => todo!(),
|
||||
ty::FnDef(def_id, generic_args) => TyKind::RigidTy(RigidTy::FnDef(
|
||||
rustc_internal::fn_def(*def_id),
|
||||
self.generic_args(generic_args),
|
||||
)),
|
||||
ty::FnPtr(_) => todo!(),
|
||||
ty::Dynamic(_, _, _) => todo!(),
|
||||
ty::Closure(_, _) => todo!(),
|
||||
ty::Generator(_, _, _) => todo!(),
|
||||
ty::Never => todo!(),
|
||||
ty::Closure(def_id, generic_args) => TyKind::RigidTy(RigidTy::Closure(
|
||||
rustc_internal::closure_def(*def_id),
|
||||
self.generic_args(generic_args),
|
||||
)),
|
||||
ty::Generator(def_id, generic_args, movability) => TyKind::RigidTy(RigidTy::Generator(
|
||||
rustc_internal::generator_def(*def_id),
|
||||
self.generic_args(generic_args),
|
||||
match movability {
|
||||
hir::Movability::Static => Movability::Static,
|
||||
hir::Movability::Movable => Movability::Movable,
|
||||
},
|
||||
)),
|
||||
ty::Never => TyKind::RigidTy(RigidTy::Never),
|
||||
ty::Tuple(fields) => TyKind::RigidTy(RigidTy::Tuple(
|
||||
fields.iter().map(|ty| self.intern_ty(ty)).collect(),
|
||||
)),
|
||||
|
@ -155,6 +158,24 @@ impl<'tcx> Tables<'tcx> {
|
|||
self.types.push(ty);
|
||||
stable_mir::ty::Ty(id)
|
||||
}
|
||||
|
||||
fn generic_args(
|
||||
&mut self,
|
||||
generic_args: &ty::GenericArgs<'tcx>,
|
||||
) -> stable_mir::ty::GenericArgs {
|
||||
GenericArgs(
|
||||
generic_args
|
||||
.iter()
|
||||
.map(|arg| match arg.unpack() {
|
||||
ty::GenericArgKind::Lifetime(region) => {
|
||||
GenericArgKind::Lifetime(opaque(®ion))
|
||||
}
|
||||
ty::GenericArgKind::Type(ty) => GenericArgKind::Type(self.intern_ty(ty)),
|
||||
ty::GenericArgKind::Const(const_) => GenericArgKind::Const(opaque(&const_)),
|
||||
})
|
||||
.collect(),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
/// Build a stable mir crate from a given crate number.
|
||||
|
|
|
@ -25,12 +25,17 @@ pub enum RigidTy {
|
|||
Int(IntTy),
|
||||
Uint(UintTy),
|
||||
Float(FloatTy),
|
||||
Adt(AdtDef, AdtSubsts),
|
||||
Adt(AdtDef, GenericArgs),
|
||||
Foreign(ForeignDef),
|
||||
Str,
|
||||
Array(Ty, Const),
|
||||
Slice(Ty),
|
||||
RawPtr(Ty, Mutability),
|
||||
Ref(Region, Ty, Mutability),
|
||||
FnDef(FnDef, GenericArgs),
|
||||
Closure(ClosureDef, GenericArgs),
|
||||
Generator(GeneratorDef, GenericArgs, Movability),
|
||||
Never,
|
||||
Tuple(Vec<Ty>),
|
||||
}
|
||||
|
||||
|
@ -60,17 +65,33 @@ pub enum FloatTy {
|
|||
F64,
|
||||
}
|
||||
|
||||
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
|
||||
pub enum Movability {
|
||||
Static,
|
||||
Movable,
|
||||
}
|
||||
|
||||
#[derive(Clone, PartialEq, Eq, Debug)]
|
||||
pub struct ForeignDef(pub(crate) DefId);
|
||||
|
||||
#[derive(Clone, PartialEq, Eq, Debug)]
|
||||
pub struct FnDef(pub(crate) DefId);
|
||||
|
||||
#[derive(Clone, PartialEq, Eq, Debug)]
|
||||
pub struct ClosureDef(pub(crate) DefId);
|
||||
|
||||
#[derive(Clone, PartialEq, Eq, Debug)]
|
||||
pub struct GeneratorDef(pub(crate) DefId);
|
||||
|
||||
#[derive(Clone, PartialEq, Eq, Debug)]
|
||||
pub struct AdtDef(pub(crate) DefId);
|
||||
|
||||
#[derive(Clone, Debug)]
|
||||
pub struct AdtSubsts(pub Vec<GenericArgKind>);
|
||||
pub struct GenericArgs(pub Vec<GenericArgKind>);
|
||||
|
||||
#[derive(Clone, Debug)]
|
||||
pub enum GenericArgKind {
|
||||
// FIXME add proper region
|
||||
Lifetime(Region),
|
||||
Type(Ty),
|
||||
// FIXME add proper const
|
||||
Const(Const),
|
||||
}
|
||||
|
|
|
@ -10,9 +10,11 @@ use rustc_infer::traits::util::elaborate;
|
|||
use rustc_infer::traits::Reveal;
|
||||
use rustc_middle::traits::solve::inspect::CandidateKind;
|
||||
use rustc_middle::traits::solve::{CanonicalResponse, Certainty, Goal, MaybeCause, QueryResult};
|
||||
use rustc_middle::ty::fast_reject::TreatProjections;
|
||||
use rustc_middle::ty::TypeFoldable;
|
||||
use rustc_middle::ty::fast_reject::{SimplifiedType, TreatParams};
|
||||
use rustc_middle::ty::TypeVisitableExt;
|
||||
use rustc_middle::ty::{self, Ty, TyCtxt};
|
||||
use rustc_middle::ty::{fast_reject, TypeFoldable};
|
||||
use rustc_span::ErrorGuaranteed;
|
||||
use std::fmt::Debug;
|
||||
|
||||
pub(super) mod structural_traits;
|
||||
|
@ -109,10 +111,10 @@ pub(super) trait GoalKind<'tcx>:
|
|||
|
||||
fn trait_def_id(self, tcx: TyCtxt<'tcx>) -> DefId;
|
||||
|
||||
// Try equating an assumption predicate against a goal's predicate. If it
|
||||
// holds, then execute the `then` callback, which should do any additional
|
||||
// work, then produce a response (typically by executing
|
||||
// [`EvalCtxt::evaluate_added_goals_and_make_canonical_response`]).
|
||||
/// Try equating an assumption predicate against a goal's predicate. If it
|
||||
/// holds, then execute the `then` callback, which should do any additional
|
||||
/// work, then produce a response (typically by executing
|
||||
/// [`EvalCtxt::evaluate_added_goals_and_make_canonical_response`]).
|
||||
fn probe_and_match_goal_against_assumption(
|
||||
ecx: &mut EvalCtxt<'_, 'tcx>,
|
||||
goal: Goal<'tcx, Self>,
|
||||
|
@ -120,9 +122,9 @@ pub(super) trait GoalKind<'tcx>:
|
|||
then: impl FnOnce(&mut EvalCtxt<'_, 'tcx>) -> QueryResult<'tcx>,
|
||||
) -> QueryResult<'tcx>;
|
||||
|
||||
// Consider a clause, which consists of a "assumption" and some "requirements",
|
||||
// to satisfy a goal. If the requirements hold, then attempt to satisfy our
|
||||
// goal by equating it with the assumption.
|
||||
/// Consider a clause, which consists of a "assumption" and some "requirements",
|
||||
/// to satisfy a goal. If the requirements hold, then attempt to satisfy our
|
||||
/// goal by equating it with the assumption.
|
||||
fn consider_implied_clause(
|
||||
ecx: &mut EvalCtxt<'_, 'tcx>,
|
||||
goal: Goal<'tcx, Self>,
|
||||
|
@ -149,9 +151,9 @@ pub(super) trait GoalKind<'tcx>:
|
|||
})
|
||||
}
|
||||
|
||||
// Consider a clause specifically for a `dyn Trait` self type. This requires
|
||||
// additionally checking all of the supertraits and object bounds to hold,
|
||||
// since they're not implied by the well-formedness of the object type.
|
||||
/// Consider a clause specifically for a `dyn Trait` self type. This requires
|
||||
/// additionally checking all of the supertraits and object bounds to hold,
|
||||
/// since they're not implied by the well-formedness of the object type.
|
||||
fn consider_object_bound_candidate(
|
||||
ecx: &mut EvalCtxt<'_, 'tcx>,
|
||||
goal: Goal<'tcx, Self>,
|
||||
|
@ -182,96 +184,113 @@ pub(super) trait GoalKind<'tcx>:
|
|||
impl_def_id: DefId,
|
||||
) -> QueryResult<'tcx>;
|
||||
|
||||
// A type implements an `auto trait` if its components do as well. These components
|
||||
// are given by built-in rules from [`instantiate_constituent_tys_for_auto_trait`].
|
||||
/// If the predicate contained an error, we want to avoid emitting unnecessary trait
|
||||
/// errors but still want to emit errors for other trait goals. We have some special
|
||||
/// handling for this case.
|
||||
///
|
||||
/// Trait goals always hold while projection goals never do. This is a bit arbitrary
|
||||
/// but prevents incorrect normalization while hiding any trait errors.
|
||||
fn consider_error_guaranteed_candidate(
|
||||
ecx: &mut EvalCtxt<'_, 'tcx>,
|
||||
guar: ErrorGuaranteed,
|
||||
) -> QueryResult<'tcx>;
|
||||
|
||||
/// A type implements an `auto trait` if its components do as well.
|
||||
///
|
||||
/// These components are given by built-in rules from
|
||||
/// [`structural_traits::instantiate_constituent_tys_for_auto_trait`].
|
||||
fn consider_auto_trait_candidate(
|
||||
ecx: &mut EvalCtxt<'_, 'tcx>,
|
||||
goal: Goal<'tcx, Self>,
|
||||
) -> QueryResult<'tcx>;
|
||||
|
||||
// A trait alias holds if the RHS traits and `where` clauses hold.
|
||||
/// A trait alias holds if the RHS traits and `where` clauses hold.
|
||||
fn consider_trait_alias_candidate(
|
||||
ecx: &mut EvalCtxt<'_, 'tcx>,
|
||||
goal: Goal<'tcx, Self>,
|
||||
) -> QueryResult<'tcx>;
|
||||
|
||||
// A type is `Copy` or `Clone` if its components are `Sized`. These components
|
||||
// are given by built-in rules from [`instantiate_constituent_tys_for_sized_trait`].
|
||||
/// A type is `Copy` or `Clone` if its components are `Sized`.
|
||||
///
|
||||
/// These components are given by built-in rules from
|
||||
/// [`structural_traits::instantiate_constituent_tys_for_sized_trait`].
|
||||
fn consider_builtin_sized_candidate(
|
||||
ecx: &mut EvalCtxt<'_, 'tcx>,
|
||||
goal: Goal<'tcx, Self>,
|
||||
) -> QueryResult<'tcx>;
|
||||
|
||||
// A type is `Copy` or `Clone` if its components are `Copy` or `Clone`. These
|
||||
// components are given by built-in rules from [`instantiate_constituent_tys_for_copy_clone_trait`].
|
||||
/// A type is `Copy` or `Clone` if its components are `Copy` or `Clone`.
|
||||
///
|
||||
/// These components are given by built-in rules from
|
||||
/// [`structural_traits::instantiate_constituent_tys_for_copy_clone_trait`].
|
||||
fn consider_builtin_copy_clone_candidate(
|
||||
ecx: &mut EvalCtxt<'_, 'tcx>,
|
||||
goal: Goal<'tcx, Self>,
|
||||
) -> QueryResult<'tcx>;
|
||||
|
||||
// A type is `PointerLike` if we can compute its layout, and that layout
|
||||
// matches the layout of `usize`.
|
||||
/// A type is `PointerLike` if we can compute its layout, and that layout
|
||||
/// matches the layout of `usize`.
|
||||
fn consider_builtin_pointer_like_candidate(
|
||||
ecx: &mut EvalCtxt<'_, 'tcx>,
|
||||
goal: Goal<'tcx, Self>,
|
||||
) -> QueryResult<'tcx>;
|
||||
|
||||
// A type is a `FnPtr` if it is of `FnPtr` type.
|
||||
/// A type is a `FnPtr` if it is of `FnPtr` type.
|
||||
fn consider_builtin_fn_ptr_trait_candidate(
|
||||
ecx: &mut EvalCtxt<'_, 'tcx>,
|
||||
goal: Goal<'tcx, Self>,
|
||||
) -> QueryResult<'tcx>;
|
||||
|
||||
// A callable type (a closure, fn def, or fn ptr) is known to implement the `Fn<A>`
|
||||
// family of traits where `A` is given by the signature of the type.
|
||||
/// A callable type (a closure, fn def, or fn ptr) is known to implement the `Fn<A>`
|
||||
/// family of traits where `A` is given by the signature of the type.
|
||||
fn consider_builtin_fn_trait_candidates(
|
||||
ecx: &mut EvalCtxt<'_, 'tcx>,
|
||||
goal: Goal<'tcx, Self>,
|
||||
kind: ty::ClosureKind,
|
||||
) -> QueryResult<'tcx>;
|
||||
|
||||
// `Tuple` is implemented if the `Self` type is a tuple.
|
||||
/// `Tuple` is implemented if the `Self` type is a tuple.
|
||||
fn consider_builtin_tuple_candidate(
|
||||
ecx: &mut EvalCtxt<'_, 'tcx>,
|
||||
goal: Goal<'tcx, Self>,
|
||||
) -> QueryResult<'tcx>;
|
||||
|
||||
// `Pointee` is always implemented.
|
||||
//
|
||||
// See the projection implementation for the `Metadata` types for all of
|
||||
// the built-in types. For structs, the metadata type is given by the struct
|
||||
// tail.
|
||||
/// `Pointee` is always implemented.
|
||||
///
|
||||
/// See the projection implementation for the `Metadata` types for all of
|
||||
/// the built-in types. For structs, the metadata type is given by the struct
|
||||
/// tail.
|
||||
fn consider_builtin_pointee_candidate(
|
||||
ecx: &mut EvalCtxt<'_, 'tcx>,
|
||||
goal: Goal<'tcx, Self>,
|
||||
) -> QueryResult<'tcx>;
|
||||
|
||||
// A generator (that comes from an `async` desugaring) is known to implement
|
||||
// `Future<Output = O>`, where `O` is given by the generator's return type
|
||||
// that was computed during type-checking.
|
||||
/// A generator (that comes from an `async` desugaring) is known to implement
|
||||
/// `Future<Output = O>`, where `O` is given by the generator's return type
|
||||
/// that was computed during type-checking.
|
||||
fn consider_builtin_future_candidate(
|
||||
ecx: &mut EvalCtxt<'_, 'tcx>,
|
||||
goal: Goal<'tcx, Self>,
|
||||
) -> QueryResult<'tcx>;
|
||||
|
||||
// A generator (that doesn't come from an `async` desugaring) is known to
|
||||
// implement `Generator<R, Yield = Y, Return = O>`, given the resume, yield,
|
||||
// and return types of the generator computed during type-checking.
|
||||
/// A generator (that doesn't come from an `async` desugaring) is known to
|
||||
/// implement `Generator<R, Yield = Y, Return = O>`, given the resume, yield,
|
||||
/// and return types of the generator computed during type-checking.
|
||||
fn consider_builtin_generator_candidate(
|
||||
ecx: &mut EvalCtxt<'_, 'tcx>,
|
||||
goal: Goal<'tcx, Self>,
|
||||
) -> QueryResult<'tcx>;
|
||||
|
||||
// The most common forms of unsizing are array to slice, and concrete (Sized)
|
||||
// type into a `dyn Trait`. ADTs and Tuples can also have their final field
|
||||
// unsized if it's generic.
|
||||
/// The most common forms of unsizing are array to slice, and concrete (Sized)
|
||||
/// type into a `dyn Trait`. ADTs and Tuples can also have their final field
|
||||
/// unsized if it's generic.
|
||||
fn consider_builtin_unsize_candidate(
|
||||
ecx: &mut EvalCtxt<'_, 'tcx>,
|
||||
goal: Goal<'tcx, Self>,
|
||||
) -> QueryResult<'tcx>;
|
||||
|
||||
// `dyn Trait1` can be unsized to `dyn Trait2` if they are the same trait, or
|
||||
// if `Trait2` is a (transitive) supertrait of `Trait2`.
|
||||
/// `dyn Trait1` can be unsized to `dyn Trait2` if they are the same trait, or
|
||||
/// if `Trait2` is a (transitive) supertrait of `Trait2`.
|
||||
fn consider_builtin_dyn_upcast_candidates(
|
||||
ecx: &mut EvalCtxt<'_, 'tcx>,
|
||||
goal: Goal<'tcx, Self>,
|
||||
|
@ -299,35 +318,66 @@ impl<'tcx> EvalCtxt<'_, 'tcx> {
|
|||
goal: Goal<'tcx, G>,
|
||||
) -> Vec<Candidate<'tcx>> {
|
||||
debug_assert_eq!(goal, self.resolve_vars_if_possible(goal));
|
||||
if let Some(ambig) = self.assemble_self_ty_infer_ambiguity_response(goal) {
|
||||
return ambig;
|
||||
}
|
||||
|
||||
// HACK: `_: Trait` is ambiguous, because it may be satisfied via a builtin rule,
|
||||
// object bound, alias bound, etc. We are unable to determine this until we can at
|
||||
// least structurally resolve the type one layer.
|
||||
if goal.predicate.self_ty().is_ty_var() {
|
||||
return vec![Candidate {
|
||||
let mut candidates = self.assemble_candidates_via_self_ty(goal);
|
||||
|
||||
self.assemble_blanket_impl_candidates(goal, &mut candidates);
|
||||
|
||||
self.assemble_param_env_candidates(goal, &mut candidates);
|
||||
|
||||
candidates
|
||||
}
|
||||
|
||||
/// `?0: Trait` is ambiguous, because it may be satisfied via a builtin rule,
|
||||
/// object bound, alias bound, etc. We are unable to determine this until we can at
|
||||
/// least structurally resolve the type one layer.
|
||||
///
|
||||
/// It would also require us to consider all impls of the trait, which is both pretty
|
||||
/// bad for perf and would also constrain the self type if there is just a single impl.
|
||||
fn assemble_self_ty_infer_ambiguity_response<G: GoalKind<'tcx>>(
|
||||
&mut self,
|
||||
goal: Goal<'tcx, G>,
|
||||
) -> Option<Vec<Candidate<'tcx>>> {
|
||||
goal.predicate.self_ty().is_ty_var().then(|| {
|
||||
vec![Candidate {
|
||||
source: CandidateSource::BuiltinImpl(BuiltinImplSource::Ambiguity),
|
||||
result: self
|
||||
.evaluate_added_goals_and_make_canonical_response(Certainty::AMBIGUOUS)
|
||||
.unwrap(),
|
||||
}];
|
||||
}]
|
||||
})
|
||||
}
|
||||
|
||||
/// Assemble candidates which apply to the self type. This only looks at candidate which
|
||||
/// apply to the specific self type and ignores all others.
|
||||
///
|
||||
/// Returns `None` if the self type is still ambiguous.
|
||||
fn assemble_candidates_via_self_ty<G: GoalKind<'tcx>>(
|
||||
&mut self,
|
||||
goal: Goal<'tcx, G>,
|
||||
) -> Vec<Candidate<'tcx>> {
|
||||
debug_assert_eq!(goal, self.resolve_vars_if_possible(goal));
|
||||
if let Some(ambig) = self.assemble_self_ty_infer_ambiguity_response(goal) {
|
||||
return ambig;
|
||||
}
|
||||
|
||||
let mut candidates = Vec::new();
|
||||
|
||||
self.assemble_candidates_after_normalizing_self_ty(goal, &mut candidates);
|
||||
|
||||
self.assemble_impl_candidates(goal, &mut candidates);
|
||||
self.assemble_non_blanket_impl_candidates(goal, &mut candidates);
|
||||
|
||||
self.assemble_builtin_impl_candidates(goal, &mut candidates);
|
||||
|
||||
self.assemble_param_env_candidates(goal, &mut candidates);
|
||||
|
||||
self.assemble_alias_bound_candidates(goal, &mut candidates);
|
||||
|
||||
self.assemble_object_bound_candidates(goal, &mut candidates);
|
||||
|
||||
self.assemble_coherence_unknowable_candidates(goal, &mut candidates);
|
||||
|
||||
self.assemble_candidates_after_normalizing_self_ty(goal, &mut candidates);
|
||||
|
||||
candidates
|
||||
}
|
||||
|
||||
|
@ -385,7 +435,7 @@ impl<'tcx> EvalCtxt<'_, 'tcx> {
|
|||
// have a `Normalized` candidate. This doesn't work as long as we
|
||||
// use `CandidateSource` in winnowing.
|
||||
let goal = goal.with(tcx, goal.predicate.with_self_ty(tcx, normalized_ty));
|
||||
Ok(ecx.assemble_and_evaluate_candidates(goal))
|
||||
Ok(ecx.assemble_candidates_via_self_ty(goal))
|
||||
},
|
||||
)
|
||||
});
|
||||
|
@ -396,22 +446,125 @@ impl<'tcx> EvalCtxt<'_, 'tcx> {
|
|||
}
|
||||
|
||||
#[instrument(level = "debug", skip_all)]
|
||||
fn assemble_impl_candidates<G: GoalKind<'tcx>>(
|
||||
fn assemble_non_blanket_impl_candidates<G: GoalKind<'tcx>>(
|
||||
&mut self,
|
||||
goal: Goal<'tcx, G>,
|
||||
candidates: &mut Vec<Candidate<'tcx>>,
|
||||
) {
|
||||
let tcx = self.tcx();
|
||||
tcx.for_each_relevant_impl_treating_projections(
|
||||
goal.predicate.trait_def_id(tcx),
|
||||
goal.predicate.self_ty(),
|
||||
TreatProjections::NextSolverLookup,
|
||||
|impl_def_id| match G::consider_impl_candidate(self, goal, impl_def_id) {
|
||||
let self_ty = goal.predicate.self_ty();
|
||||
let trait_impls = tcx.trait_impls_of(goal.predicate.trait_def_id(tcx));
|
||||
let mut consider_impls_for_simplified_type = |simp| {
|
||||
if let Some(impls_for_type) = trait_impls.non_blanket_impls().get(&simp) {
|
||||
for &impl_def_id in impls_for_type {
|
||||
match G::consider_impl_candidate(self, goal, impl_def_id) {
|
||||
Ok(result) => candidates
|
||||
.push(Candidate { source: CandidateSource::Impl(impl_def_id), result }),
|
||||
Err(NoSolution) => (),
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
match self_ty.kind() {
|
||||
ty::Bool
|
||||
| ty::Char
|
||||
| ty::Int(_)
|
||||
| ty::Uint(_)
|
||||
| ty::Float(_)
|
||||
| ty::Adt(_, _)
|
||||
| ty::Foreign(_)
|
||||
| ty::Str
|
||||
| ty::Array(_, _)
|
||||
| ty::Slice(_)
|
||||
| ty::RawPtr(_)
|
||||
| ty::Ref(_, _, _)
|
||||
| ty::FnDef(_, _)
|
||||
| ty::FnPtr(_)
|
||||
| ty::Dynamic(_, _, _)
|
||||
| ty::Closure(_, _)
|
||||
| ty::Generator(_, _, _)
|
||||
| ty::Never
|
||||
| ty::Tuple(_) => {
|
||||
let simp =
|
||||
fast_reject::simplify_type(tcx, self_ty, TreatParams::ForLookup).unwrap();
|
||||
consider_impls_for_simplified_type(simp);
|
||||
}
|
||||
|
||||
// HACK: For integer and float variables we have to manually look at all impls
|
||||
// which have some integer or float as a self type.
|
||||
ty::Infer(ty::IntVar(_)) => {
|
||||
use ty::IntTy::*;
|
||||
use ty::UintTy::*;
|
||||
// This causes a compiler error if any new integer kinds are added.
|
||||
let (I8 | I16 | I32 | I64 | I128 | Isize): ty::IntTy;
|
||||
let (U8 | U16 | U32 | U64 | U128 | Usize): ty::UintTy;
|
||||
let possible_integers = [
|
||||
// signed integers
|
||||
SimplifiedType::Int(I8),
|
||||
SimplifiedType::Int(I16),
|
||||
SimplifiedType::Int(I32),
|
||||
SimplifiedType::Int(I64),
|
||||
SimplifiedType::Int(I128),
|
||||
SimplifiedType::Int(Isize),
|
||||
// unsigned integers
|
||||
SimplifiedType::Uint(U8),
|
||||
SimplifiedType::Uint(U16),
|
||||
SimplifiedType::Uint(U32),
|
||||
SimplifiedType::Uint(U64),
|
||||
SimplifiedType::Uint(U128),
|
||||
SimplifiedType::Uint(Usize),
|
||||
];
|
||||
for simp in possible_integers {
|
||||
consider_impls_for_simplified_type(simp);
|
||||
}
|
||||
}
|
||||
|
||||
ty::Infer(ty::FloatVar(_)) => {
|
||||
// This causes a compiler error if any new float kinds are added.
|
||||
let (ty::FloatTy::F32 | ty::FloatTy::F64);
|
||||
let possible_floats = [
|
||||
SimplifiedType::Float(ty::FloatTy::F32),
|
||||
SimplifiedType::Float(ty::FloatTy::F64),
|
||||
];
|
||||
|
||||
for simp in possible_floats {
|
||||
consider_impls_for_simplified_type(simp);
|
||||
}
|
||||
}
|
||||
|
||||
// The only traits applying to aliases and placeholders are blanket impls.
|
||||
//
|
||||
// Impls which apply to an alias after normalization are handled by
|
||||
// `assemble_candidates_after_normalizing_self_ty`.
|
||||
ty::Alias(_, _) | ty::Placeholder(..) | ty::Error(_) => (),
|
||||
|
||||
// FIXME: These should ideally not exist as a self type. It would be nice for
|
||||
// the builtin auto trait impls of generators should instead directly recurse
|
||||
// into the witness.
|
||||
ty::GeneratorWitness(_) | ty::GeneratorWitnessMIR(_, _) => (),
|
||||
|
||||
// These variants should not exist as a self type.
|
||||
ty::Infer(ty::TyVar(_) | ty::FreshTy(_) | ty::FreshIntTy(_) | ty::FreshFloatTy(_))
|
||||
| ty::Param(_)
|
||||
| ty::Bound(_, _) => bug!("unexpected self type: {self_ty}"),
|
||||
}
|
||||
}
|
||||
|
||||
fn assemble_blanket_impl_candidates<G: GoalKind<'tcx>>(
|
||||
&mut self,
|
||||
goal: Goal<'tcx, G>,
|
||||
candidates: &mut Vec<Candidate<'tcx>>,
|
||||
) {
|
||||
let tcx = self.tcx();
|
||||
let trait_impls = tcx.trait_impls_of(goal.predicate.trait_def_id(tcx));
|
||||
for &impl_def_id in trait_impls.blanket_impls() {
|
||||
match G::consider_impl_candidate(self, goal, impl_def_id) {
|
||||
Ok(result) => candidates
|
||||
.push(Candidate { source: CandidateSource::Impl(impl_def_id), result }),
|
||||
Err(NoSolution) => (),
|
||||
},
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[instrument(level = "debug", skip_all)]
|
||||
|
@ -420,8 +573,9 @@ impl<'tcx> EvalCtxt<'_, 'tcx> {
|
|||
goal: Goal<'tcx, G>,
|
||||
candidates: &mut Vec<Candidate<'tcx>>,
|
||||
) {
|
||||
let lang_items = self.tcx().lang_items();
|
||||
let trait_def_id = goal.predicate.trait_def_id(self.tcx());
|
||||
let tcx = self.tcx();
|
||||
let lang_items = tcx.lang_items();
|
||||
let trait_def_id = goal.predicate.trait_def_id(tcx);
|
||||
|
||||
// N.B. When assembling built-in candidates for lang items that are also
|
||||
// `auto` traits, then the auto trait candidate that is assembled in
|
||||
|
@ -430,9 +584,11 @@ impl<'tcx> EvalCtxt<'_, 'tcx> {
|
|||
// Instead of adding the logic here, it's a better idea to add it in
|
||||
// `EvalCtxt::disqualify_auto_trait_candidate_due_to_possible_impl` in
|
||||
// `solve::trait_goals` instead.
|
||||
let result = if self.tcx().trait_is_auto(trait_def_id) {
|
||||
let result = if let Err(guar) = goal.predicate.error_reported() {
|
||||
G::consider_error_guaranteed_candidate(self, guar)
|
||||
} else if tcx.trait_is_auto(trait_def_id) {
|
||||
G::consider_auto_trait_candidate(self, goal)
|
||||
} else if self.tcx().trait_is_alias(trait_def_id) {
|
||||
} else if tcx.trait_is_alias(trait_def_id) {
|
||||
G::consider_trait_alias_candidate(self, goal)
|
||||
} else if lang_items.sized_trait() == Some(trait_def_id) {
|
||||
G::consider_builtin_sized_candidate(self, goal)
|
||||
|
|
|
@ -2,7 +2,6 @@ use crate::traits::specialization_graph;
|
|||
|
||||
use super::assembly::{self, structural_traits};
|
||||
use super::EvalCtxt;
|
||||
use rustc_errors::ErrorGuaranteed;
|
||||
use rustc_hir::def::DefKind;
|
||||
use rustc_hir::def_id::DefId;
|
||||
use rustc_hir::LangItem;
|
||||
|
@ -15,7 +14,7 @@ use rustc_middle::ty::fast_reject::{DeepRejectCtxt, TreatParams};
|
|||
use rustc_middle::ty::ProjectionPredicate;
|
||||
use rustc_middle::ty::{self, Ty, TyCtxt};
|
||||
use rustc_middle::ty::{ToPredicate, TypeVisitableExt};
|
||||
use rustc_span::{sym, DUMMY_SP};
|
||||
use rustc_span::{sym, ErrorGuaranteed, DUMMY_SP};
|
||||
|
||||
impl<'tcx> EvalCtxt<'_, 'tcx> {
|
||||
#[instrument(level = "debug", skip(self), ret)]
|
||||
|
@ -246,6 +245,15 @@ impl<'tcx> assembly::GoalKind<'tcx> for ProjectionPredicate<'tcx> {
|
|||
})
|
||||
}
|
||||
|
||||
/// Fail to normalize if the predicate contains an error, alternatively, we could normalize to `ty::Error`
|
||||
/// and succeed. Can experiment with this to figure out what results in better error messages.
|
||||
fn consider_error_guaranteed_candidate(
|
||||
_ecx: &mut EvalCtxt<'_, 'tcx>,
|
||||
_guar: ErrorGuaranteed,
|
||||
) -> QueryResult<'tcx> {
|
||||
Err(NoSolution)
|
||||
}
|
||||
|
||||
fn consider_auto_trait_candidate(
|
||||
ecx: &mut EvalCtxt<'_, 'tcx>,
|
||||
goal: Goal<'tcx, Self>,
|
||||
|
|
|
@ -11,7 +11,7 @@ use rustc_middle::traits::Reveal;
|
|||
use rustc_middle::ty::fast_reject::{DeepRejectCtxt, TreatParams, TreatProjections};
|
||||
use rustc_middle::ty::{self, ToPredicate, Ty, TyCtxt};
|
||||
use rustc_middle::ty::{TraitPredicate, TypeVisitableExt};
|
||||
use rustc_span::DUMMY_SP;
|
||||
use rustc_span::{ErrorGuaranteed, DUMMY_SP};
|
||||
|
||||
impl<'tcx> assembly::GoalKind<'tcx> for TraitPredicate<'tcx> {
|
||||
fn self_ty(self) -> Ty<'tcx> {
|
||||
|
@ -78,6 +78,13 @@ impl<'tcx> assembly::GoalKind<'tcx> for TraitPredicate<'tcx> {
|
|||
})
|
||||
}
|
||||
|
||||
fn consider_error_guaranteed_candidate(
|
||||
ecx: &mut EvalCtxt<'_, 'tcx>,
|
||||
_guar: ErrorGuaranteed,
|
||||
) -> QueryResult<'tcx> {
|
||||
ecx.evaluate_added_goals_and_make_canonical_response(Certainty::Yes)
|
||||
}
|
||||
|
||||
fn probe_and_match_goal_against_assumption(
|
||||
ecx: &mut EvalCtxt<'_, 'tcx>,
|
||||
goal: Goal<'tcx, Self>,
|
||||
|
@ -686,7 +693,7 @@ impl<'tcx> EvalCtxt<'_, 'tcx> {
|
|||
| ty::Tuple(_)
|
||||
| ty::Adt(_, _)
|
||||
// FIXME: Handling opaques here is kinda sus. Especially because we
|
||||
// simplify them to PlaceholderSimplifiedType.
|
||||
// simplify them to SimplifiedType::Placeholder.
|
||||
| ty::Alias(ty::Opaque, _) => {
|
||||
let mut disqualifying_impl = None;
|
||||
self.tcx().for_each_relevant_impl_treating_projections(
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue