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:
bors 2023-07-20 16:57:05 +00:00
commit 092e4f46be
27 changed files with 619 additions and 286 deletions

View file

@ -65,8 +65,22 @@ pub fn eval_unevaluated_mir_constant_to_valtree(
&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);

View file

@ -1003,7 +1003,7 @@ pub fn span_warn_with_code(
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 @@ pub fn span_bug(&self, span: impl Into<MultiSpan>, msg: impl Into<DiagnosticMess
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 @@ fn abort_if_errors(&mut self) {
}
#[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 @@ fn emit_diag_at_span(&mut self, mut diag: Diagnostic, sp: impl Into<MultiSpan>)
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 @@ fn delay_span_bug(
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()
}

View file

@ -1147,7 +1147,7 @@ pub fn span_err<S: Into<MultiSpan>>(&self, sp: S, msg: impl Into<DiagnosticMessa
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) {

View file

@ -568,10 +568,10 @@ struct DisableAutoTraitVisitor<'tcx> {
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 visit_ty(&mut self, t: Ty<'tcx>) -> ControlFlow<Self::BreakTy> {
}
}
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 visit_ty(&mut self, t: Ty<'tcx>) -> ControlFlow<Self::BreakTy> {
ControlFlow::Continue(())
}
_ => t.super_visit_with(self),
_ => ty.super_visit_with(self),
}
}
}

View file

@ -6,35 +6,33 @@
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,
}
}

View file

@ -15,7 +15,6 @@
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 @@ pub fn new_misc_error(tcx: TyCtxt<'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))

View file

@ -247,7 +247,7 @@ pub fn struct_span_err<S: Into<MultiSpan>>(
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)
}

View file

@ -8,7 +8,6 @@
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 @@ pub(super) fn parse_pat_before_ty(
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))

View file

@ -677,7 +677,7 @@ pub fn warn(&self, msg: impl Into<DiagnosticMessage>) {
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)
}

View file

@ -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 @@ pub fn adt_def(&mut self, did: DefId) -> stable_mir::ty::AdtDef {
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() {

View file

@ -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 @@ fn rustc_ty_to_ty(&mut self, ty: Ty<'tcx>) -> TyKind {
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(&region))
}
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 @@ fn rustc_ty_to_ty(&mut self, ty: Ty<'tcx>) -> TyKind {
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 @@ fn intern_ty(&mut self, ty: Ty<'tcx>) -> stable_mir::ty::Ty {
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(&region))
}
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.

View file

@ -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),
}

View file

@ -10,9 +10,11 @@
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 @@ fn probe_and_match_goal_against_assumption(
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 @@ fn consider_alias_bound_candidate(
})
}
// 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 @@ fn consider_impl_candidate(
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 @@ pub(super) fn assemble_and_evaluate_candidates<G: GoalKind<'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 @@ fn assemble_candidates_after_normalizing_self_ty<G: GoalKind<'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 @@ fn assemble_candidates_after_normalizing_self_ty<G: GoalKind<'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 @@ fn assemble_builtin_impl_candidates<G: GoalKind<'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 @@ fn assemble_builtin_impl_candidates<G: GoalKind<'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)

View file

@ -2,7 +2,6 @@
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::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 @@ fn consider_impl_candidate(
})
}
/// 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>,

View file

@ -11,7 +11,7 @@
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 @@ fn consider_impl_candidate(
})
}
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 @@ fn disqualify_auto_trait_candidate_due_to_possible_impl(
| 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(

View file

@ -2087,10 +2087,11 @@ fn run(self, builder: &Builder<'_>) {
let mut tool = tool::ErrorIndex::command(builder);
tool.arg("markdown").arg(&output);
let _guard =
let guard =
builder.msg(Kind::Test, compiler.stage, "error-index", compiler.host, compiler.host);
let _time = util::timeit(&builder);
builder.run_quiet(&mut tool);
drop(guard);
// The tests themselves need to link to std, so make sure it is
// available.
builder.ensure(compile::Std::new(compiler, compiler.host));

View file

@ -12,6 +12,7 @@
use rustc_hir::def_id::{DefId, DefIdSet, LocalDefId};
use rustc_hir::Mutability;
use rustc_metadata::creader::{CStore, LoadedMacro};
use rustc_middle::ty::fast_reject::SimplifiedType;
use rustc_middle::ty::{self, TyCtxt};
use rustc_span::hygiene::MacroKind;
use rustc_span::symbol::{kw, sym, Symbol};
@ -314,9 +315,8 @@ pub(crate) fn build_impls(
// * https://github.com/rust-lang/rust/pull/99917 — where the feature got used
// * https://github.com/rust-lang/rust/issues/53487 — overall tracking issue for Error
if tcx.has_attr(did, sym::rustc_has_incoherent_inherent_impls) {
use rustc_middle::ty::fast_reject::SimplifiedType::*;
let type_ =
if tcx.is_trait(did) { TraitSimplifiedType(did) } else { AdtSimplifiedType(did) };
if tcx.is_trait(did) { SimplifiedType::Trait(did) } else { SimplifiedType::Adt(did) };
for &did in tcx.incoherent_impls(type_) {
build_impl(cx, did, attrs, ret);
}

View file

@ -1776,7 +1776,6 @@ pub(crate) fn from_symbol(s: Symbol) -> Option<PrimitiveType> {
}
pub(crate) fn simplified_types() -> &'static SimplifiedTypes {
use ty::fast_reject::SimplifiedType::*;
use ty::{FloatTy, IntTy, UintTy};
use PrimitiveType::*;
static CELL: OnceCell<SimplifiedTypes> = OnceCell::new();
@ -1784,38 +1783,38 @@ pub(crate) fn simplified_types() -> &'static SimplifiedTypes {
let single = |x| iter::once(x).collect();
CELL.get_or_init(move || {
map! {
Isize => single(IntSimplifiedType(IntTy::Isize)),
I8 => single(IntSimplifiedType(IntTy::I8)),
I16 => single(IntSimplifiedType(IntTy::I16)),
I32 => single(IntSimplifiedType(IntTy::I32)),
I64 => single(IntSimplifiedType(IntTy::I64)),
I128 => single(IntSimplifiedType(IntTy::I128)),
Usize => single(UintSimplifiedType(UintTy::Usize)),
U8 => single(UintSimplifiedType(UintTy::U8)),
U16 => single(UintSimplifiedType(UintTy::U16)),
U32 => single(UintSimplifiedType(UintTy::U32)),
U64 => single(UintSimplifiedType(UintTy::U64)),
U128 => single(UintSimplifiedType(UintTy::U128)),
F32 => single(FloatSimplifiedType(FloatTy::F32)),
F64 => single(FloatSimplifiedType(FloatTy::F64)),
Str => single(StrSimplifiedType),
Bool => single(BoolSimplifiedType),
Char => single(CharSimplifiedType),
Array => single(ArraySimplifiedType),
Slice => single(SliceSimplifiedType),
Isize => single(SimplifiedType::Int(IntTy::Isize)),
I8 => single(SimplifiedType::Int(IntTy::I8)),
I16 => single(SimplifiedType::Int(IntTy::I16)),
I32 => single(SimplifiedType::Int(IntTy::I32)),
I64 => single(SimplifiedType::Int(IntTy::I64)),
I128 => single(SimplifiedType::Int(IntTy::I128)),
Usize => single(SimplifiedType::Uint(UintTy::Usize)),
U8 => single(SimplifiedType::Uint(UintTy::U8)),
U16 => single(SimplifiedType::Uint(UintTy::U16)),
U32 => single(SimplifiedType::Uint(UintTy::U32)),
U64 => single(SimplifiedType::Uint(UintTy::U64)),
U128 => single(SimplifiedType::Uint(UintTy::U128)),
F32 => single(SimplifiedType::Float(FloatTy::F32)),
F64 => single(SimplifiedType::Float(FloatTy::F64)),
Str => single(SimplifiedType::Str),
Bool => single(SimplifiedType::Bool),
Char => single(SimplifiedType::Char),
Array => single(SimplifiedType::Array),
Slice => single(SimplifiedType::Slice),
// FIXME: If we ever add an inherent impl for tuples
// with different lengths, they won't show in rustdoc.
//
// Either manually update this arrayvec at this point
// or start with a more complex refactoring.
Tuple => [TupleSimplifiedType(1), TupleSimplifiedType(2), TupleSimplifiedType(3)].into(),
Unit => single(TupleSimplifiedType(0)),
RawPointer => [PtrSimplifiedType(Mutability::Not), PtrSimplifiedType(Mutability::Mut)].into_iter().collect(),
Reference => [RefSimplifiedType(Mutability::Not), RefSimplifiedType(Mutability::Mut)].into_iter().collect(),
Tuple => [SimplifiedType::Tuple(1), SimplifiedType::Tuple(2), SimplifiedType::Tuple(3)].into(),
Unit => single(SimplifiedType::Tuple(0)),
RawPointer => [SimplifiedType::Ptr(Mutability::Not), SimplifiedType::Ptr(Mutability::Mut)].into_iter().collect(),
Reference => [SimplifiedType::Ref(Mutability::Not), SimplifiedType::Ref(Mutability::Mut)].into_iter().collect(),
// FIXME: This will be wrong if we ever add inherent impls
// for function pointers.
Fn => single(FunctionSimplifiedType(1)),
Never => single(NeverSimplifiedType),
Fn => single(SimplifiedType::Function(1)),
Never => single(SimplifiedType::Never),
}
})
}

View file

@ -820,6 +820,7 @@ fn assoc_method(
let header = meth.fn_header(tcx).expect("Trying to get header from a non-function item");
let name = meth.name.as_ref().unwrap();
let vis = visibility_print_with_space(meth.visibility(tcx), meth.item_id, cx).to_string();
let defaultness = print_default_space(meth.is_default());
// FIXME: Once https://github.com/rust-lang/rust/issues/67792 is implemented, we can remove
// this condition.
let constness = match render_mode {
@ -830,7 +831,6 @@ fn assoc_method(
};
let asyncness = header.asyncness.print_with_space();
let unsafety = header.unsafety.print_with_space();
let defaultness = print_default_space(meth.is_default());
let abi = print_abi_with_space(header.abi).to_string();
let href = assoc_href_attr(meth, link, cx);
@ -838,10 +838,10 @@ fn assoc_method(
let generics_len = format!("{:#}", g.print(cx)).len();
let mut header_len = "fn ".len()
+ vis.len()
+ defaultness.len()
+ constness.len()
+ asyncness.len()
+ unsafety.len()
+ defaultness.len()
+ abi.len()
+ name.as_str().len()
+ generics_len;
@ -860,14 +860,14 @@ fn assoc_method(
w.reserve(header_len + "<a href=\"\" class=\"fn\">{".len() + "</a>".len());
write!(
w,
"{indent}{vis}{constness}{asyncness}{unsafety}{defaultness}{abi}fn \
"{indent}{vis}{defaultness}{constness}{asyncness}{unsafety}{abi}fn \
<a{href} class=\"fn\">{name}</a>{generics}{decl}{notable_traits}{where_clause}",
indent = indent_str,
vis = vis,
defaultness = defaultness,
constness = constness,
asyncness = asyncness,
unsafety = unsafety,
defaultness = defaultness,
abi = abi,
href = href,
name = name,

View file

@ -776,7 +776,6 @@ table,
}
#crate-search {
min-width: 115px;
/* keep these two in sync with "@-moz-document url-prefix()" below */
padding: 0 23px 0 4px;
/* prevents the <select> from overflowing the containing div in case it's shrunk */
max-width: 100%;
@ -798,14 +797,6 @@ table,
#crate-search:hover, #crate-search:focus {
border-color: var(--crate-search-hover-border);
}
/* cancel stylistic differences in padding in firefox
for "appearance: none"-style (or equivalent) <select>s */
@-moz-document url-prefix() {
#crate-search {
padding-left: 0px; /* == 4px - 4px */
padding-right: 19px; /* == 23px - 4px */
}
}
/* pseudo-element for holding the dropdown-arrow image; needs to be a separate thing
so that we can apply CSS-filters to change the arrow color in themes */
#crate-search-div::after {

View file

@ -74,10 +74,10 @@ pub fn check_path(cx: &LateContext<'_>, path: &[&str]) -> bool {
let lang_items = cx.tcx.lang_items();
// This list isn't complete, but good enough for our current list of paths.
let incoherent_impls = [
SimplifiedType::FloatSimplifiedType(FloatTy::F32),
SimplifiedType::FloatSimplifiedType(FloatTy::F64),
SimplifiedType::SliceSimplifiedType,
SimplifiedType::StrSimplifiedType,
SimplifiedType::Float(FloatTy::F32),
SimplifiedType::Float(FloatTy::F64),
SimplifiedType::Slice,
SimplifiedType::Str,
]
.iter()
.flat_map(|&ty| cx.tcx.incoherent_impls(ty).iter().copied());

View file

@ -100,10 +100,7 @@
use rustc_middle::ty as rustc_ty;
use rustc_middle::ty::adjustment::{Adjust, Adjustment, AutoBorrow};
use rustc_middle::ty::binding::BindingMode;
use rustc_middle::ty::fast_reject::SimplifiedType::{
ArraySimplifiedType, BoolSimplifiedType, CharSimplifiedType, FloatSimplifiedType, IntSimplifiedType,
PtrSimplifiedType, SliceSimplifiedType, StrSimplifiedType, UintSimplifiedType,
};
use rustc_middle::ty::fast_reject::SimplifiedType;
use rustc_middle::ty::layout::IntegerExt;
use rustc_middle::ty::{
BorrowKind, ClosureKind, FloatTy, IntTy, Ty, TyCtxt, TypeAndMut, TypeVisitableExt, UintTy, UpvarCapture,
@ -512,30 +509,30 @@ pub fn path_def_id<'tcx>(cx: &LateContext<'_>, maybe_path: &impl MaybePath<'tcx>
fn find_primitive_impls<'tcx>(tcx: TyCtxt<'tcx>, name: &str) -> impl Iterator<Item = DefId> + 'tcx {
let ty = match name {
"bool" => BoolSimplifiedType,
"char" => CharSimplifiedType,
"str" => StrSimplifiedType,
"array" => ArraySimplifiedType,
"slice" => SliceSimplifiedType,
"bool" => SimplifiedType::Bool,
"char" => SimplifiedType::Char,
"str" => SimplifiedType::Str,
"array" => SimplifiedType::Array,
"slice" => SimplifiedType::Slice,
// FIXME: rustdoc documents these two using just `pointer`.
//
// Maybe this is something we should do here too.
"const_ptr" => PtrSimplifiedType(Mutability::Not),
"mut_ptr" => PtrSimplifiedType(Mutability::Mut),
"isize" => IntSimplifiedType(IntTy::Isize),
"i8" => IntSimplifiedType(IntTy::I8),
"i16" => IntSimplifiedType(IntTy::I16),
"i32" => IntSimplifiedType(IntTy::I32),
"i64" => IntSimplifiedType(IntTy::I64),
"i128" => IntSimplifiedType(IntTy::I128),
"usize" => UintSimplifiedType(UintTy::Usize),
"u8" => UintSimplifiedType(UintTy::U8),
"u16" => UintSimplifiedType(UintTy::U16),
"u32" => UintSimplifiedType(UintTy::U32),
"u64" => UintSimplifiedType(UintTy::U64),
"u128" => UintSimplifiedType(UintTy::U128),
"f32" => FloatSimplifiedType(FloatTy::F32),
"f64" => FloatSimplifiedType(FloatTy::F64),
"const_ptr" => SimplifiedType::Ptr(Mutability::Not),
"mut_ptr" => SimplifiedType::Ptr(Mutability::Mut),
"isize" => SimplifiedType::Int(IntTy::Isize),
"i8" => SimplifiedType::Int(IntTy::I8),
"i16" => SimplifiedType::Int(IntTy::I16),
"i32" => SimplifiedType::Int(IntTy::I32),
"i64" => SimplifiedType::Int(IntTy::I64),
"i128" => SimplifiedType::Int(IntTy::I128),
"usize" => SimplifiedType::Uint(UintTy::Usize),
"u8" => SimplifiedType::Uint(UintTy::U8),
"u16" => SimplifiedType::Uint(UintTy::U16),
"u32" => SimplifiedType::Uint(UintTy::U32),
"u64" => SimplifiedType::Uint(UintTy::U64),
"u128" => SimplifiedType::Uint(UintTy::U128),
"f32" => SimplifiedType::Float(FloatTy::F32),
"f64" => SimplifiedType::Float(FloatTy::F64),
_ => return [].iter().copied(),
};

View file

@ -1,26 +1,45 @@
#![feature(min_specialization)]
// @has default_trait_method/trait.Item.html
// @has - '//*[@id="tymethod.foo"]' 'fn foo()'
// @!has - '//*[@id="tymethod.foo"]' 'default fn foo()'
// @has - '//*[@id="tymethod.bar"]' 'fn bar()'
// @!has - '//*[@id="tymethod.bar"]' 'default fn bar()'
// @has - '//*[@id="method.baz"]' 'fn baz()'
// @!has - '//*[@id="method.baz"]' 'default fn baz()'
pub trait Item {
// @has - '//*[@id="tymethod.foo"]' 'fn foo()'
// @!has - '//*[@id="tymethod.foo"]' 'default fn foo()'
fn foo();
// @has - '//*[@id="tymethod.bar"]' 'fn bar()'
// @!has - '//*[@id="tymethod.bar"]' 'default fn bar()'
fn bar();
fn baz() {}
// @has - '//*[@id="tymethod.baz"]' 'unsafe fn baz()'
// @!has - '//*[@id="tymethod.baz"]' 'default unsafe fn baz()'
unsafe fn baz();
// @has - '//*[@id="tymethod.quux"]' 'unsafe fn quux()'
// @!has - '//*[@id="tymethod.quux"]' 'default unsafe fn quux()'
unsafe fn quux();
// @has - '//*[@id="method.xyzzy"]' 'fn xyzzy()'
// @!has - '//*[@id="method.xyzzy"]' 'default fn xyzzy()'
fn xyzzy() {}
}
// @has default_trait_method/struct.Foo.html
// @has - '//*[@id="method.foo"]' 'default fn foo()'
// @has - '//*[@id="method.bar"]' 'fn bar()'
// @!has - '//*[@id="method.bar"]' 'default fn bar()'
// @has - '//*[@id="method.baz"]' 'fn baz()'
// @!has - '//*[@id="method.baz"]' 'default fn baz()'
pub struct Foo;
impl Item for Foo {
// @has - '//*[@id="method.foo"]' 'default fn foo()'
default fn foo() {}
// @has - '//*[@id="method.bar"]' 'fn bar()'
// @!has - '//*[@id="method.bar"]' 'default fn bar()'
fn bar() {}
// @has - '//*[@id="method.baz"]' 'default unsafe fn baz()'
default unsafe fn baz() {}
// @has - '//*[@id="method.quux"]' 'unsafe fn quux()'
// @!has - '//*[@id="method.quux"]' 'default unsafe fn quux()'
unsafe fn quux() {}
// @has - '//*[@id="method.xyzzy"]' 'fn xyzzy()'
// @!has - '//*[@id="method.xyzzy"]' 'default fn xyzzy()'
}

View file

@ -1,14 +1,24 @@
//run-pass
// run-pass
// revisions: opt noopt
//[noopt] compile-flags: -Copt-level=0
//[opt] compile-flags: -O
#![feature(repr_simd, platform_intrinsics)]
#![allow(incomplete_features)]
#![feature(adt_const_params)]
extern "platform-intrinsic" {
fn simd_shuffle<T, I, U>(a: T, b: T, i: I) -> U;
fn simd_shuffle16<T, U>(x: T, y: T, idx: [u32; 16]) -> U;
}
#[derive(Copy, Clone)]
#[repr(simd)]
struct Simd<T, const N: usize>([T; N]);
pub unsafe fn __shuffle_vector16<const IDX: [u32; 16], T, U>(x: T, y: T) -> U {
simd_shuffle16(x, y, IDX)
}
fn main() {
const I1: [u32; 4] = [0, 2, 4, 6];
const I2: [u32; 2] = [1, 5];
@ -21,4 +31,16 @@ fn main() {
let y: Simd<u8, 2> = simd_shuffle(a, b, I2);
assert_eq!(y.0, [1, 5]);
}
// Test that an indirection (via an unnamed constant)
// through a const generic parameter also works.
// See https://github.com/rust-lang/rust/issues/113500 for details.
let a = Simd::<u8, 16>([0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15]);
let b = Simd::<u8, 16>([16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31]);
unsafe {
__shuffle_vector16::<
{ [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16] },
Simd<u8, 16>,
Simd<u8, 16>,
>(a, b);
}
}

View file

@ -0,0 +1,27 @@
// compile-flags: -Ztrait-solver=next
// check-pass
// Checks that we do not get ambiguity by considering an impl
// multiple times if we're able to normalize the self type.
trait Trait<'a> {}
impl<'a, T: 'a> Trait<'a> for T {}
fn impls_trait<'a, T: Trait<'a>>() {}
trait Id {
type Assoc;
}
impl<T> Id for T {
type Assoc = T;
}
fn call<T>() {
impls_trait::<<T as Id>::Assoc>();
}
fn main() {
call::<()>();
impls_trait::<<<() as Id>::Assoc as Id>::Assoc>();
}

View file

@ -0,0 +1,22 @@
// compile-flags: -Ztrait-solver=next
// Test that we don't incorrectly leak unconstrained inference variables
// if the projection contained an error. This caused an ICE in writeback.
trait Mirror {
type Assoc: ?Sized;
}
struct Wrapper<T: ?Sized>(T);
impl<T: ?Sized> Mirror for Wrapper<T> {
type Assoc = T;
}
fn mirror<W: Mirror>(_: W) -> Box<W::Assoc> { todo!() }
fn type_error() -> TypeError { todo!() }
//~^ ERROR cannot find type `TypeError` in this scope
fn main() {
let x = mirror(type_error());
}

View file

@ -0,0 +1,9 @@
error[E0412]: cannot find type `TypeError` in this scope
--> $DIR/dont-normalize-proj-with-error.rs:17:20
|
LL | fn type_error() -> TypeError { todo!() }
| ^^^^^^^^^ not found in this scope
error: aborting due to previous error
For more information about this error, try `rustc --explain E0412`.