Merge pull request #4637 from rust-lang/rustup-2025-10-16
Automatic Rustup
This commit is contained in:
commit
936dda5bc7
96 changed files with 982 additions and 680 deletions
|
|
@ -86,10 +86,10 @@ impl AttributeExt for Attribute {
|
|||
/// Returns `true` if it is a sugared doc comment (`///` or `//!` for example).
|
||||
/// So `#[doc = "doc"]` (which is a doc comment) and `#[doc(...)]` (which is not
|
||||
/// a doc comment) will return `false`.
|
||||
fn is_doc_comment(&self) -> bool {
|
||||
fn is_doc_comment(&self) -> Option<Span> {
|
||||
match self.kind {
|
||||
AttrKind::Normal(..) => false,
|
||||
AttrKind::DocComment(..) => true,
|
||||
AttrKind::Normal(..) => None,
|
||||
AttrKind::DocComment(..) => Some(self.span),
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -776,7 +776,7 @@ pub trait AttributeExt: Debug {
|
|||
/// Returns `true` if it is a sugared doc comment (`///` or `//!` for example).
|
||||
/// So `#[doc = "doc"]` (which is a doc comment) and `#[doc(...)]` (which is not
|
||||
/// a doc comment) will return `false`.
|
||||
fn is_doc_comment(&self) -> bool;
|
||||
fn is_doc_comment(&self) -> Option<Span>;
|
||||
|
||||
#[inline]
|
||||
fn has_name(&self, name: Symbol) -> bool {
|
||||
|
|
@ -863,8 +863,9 @@ impl Attribute {
|
|||
AttributeExt::path_matches(self, name)
|
||||
}
|
||||
|
||||
// on ast attributes we return a bool since that's what most code already expects
|
||||
pub fn is_doc_comment(&self) -> bool {
|
||||
AttributeExt::is_doc_comment(self)
|
||||
AttributeExt::is_doc_comment(self).is_some()
|
||||
}
|
||||
|
||||
#[inline]
|
||||
|
|
|
|||
|
|
@ -31,10 +31,23 @@ pub enum AllocatorTy {
|
|||
Usize,
|
||||
}
|
||||
|
||||
/// Some allocator methods are known to the compiler: they act more like
|
||||
/// intrinsics/language primitives than library-defined functions.
|
||||
/// FIXME: ideally this would be derived from attributes like `#[rustc_allocator]`,
|
||||
/// so we don't have two sources of truth.
|
||||
#[derive(Copy, Clone, Debug)]
|
||||
pub enum SpecialAllocatorMethod {
|
||||
Alloc,
|
||||
AllocZeroed,
|
||||
Dealloc,
|
||||
Realloc,
|
||||
}
|
||||
|
||||
/// A method that will be codegened in the allocator shim.
|
||||
#[derive(Copy, Clone)]
|
||||
pub struct AllocatorMethod {
|
||||
pub name: Symbol,
|
||||
pub special: Option<SpecialAllocatorMethod>,
|
||||
pub inputs: &'static [AllocatorMethodInput],
|
||||
pub output: AllocatorTy,
|
||||
}
|
||||
|
|
@ -47,11 +60,13 @@ pub struct AllocatorMethodInput {
|
|||
pub static ALLOCATOR_METHODS: &[AllocatorMethod] = &[
|
||||
AllocatorMethod {
|
||||
name: sym::alloc,
|
||||
special: Some(SpecialAllocatorMethod::Alloc),
|
||||
inputs: &[AllocatorMethodInput { name: "layout", ty: AllocatorTy::Layout }],
|
||||
output: AllocatorTy::ResultPtr,
|
||||
},
|
||||
AllocatorMethod {
|
||||
name: sym::dealloc,
|
||||
special: Some(SpecialAllocatorMethod::Dealloc),
|
||||
inputs: &[
|
||||
AllocatorMethodInput { name: "ptr", ty: AllocatorTy::Ptr },
|
||||
AllocatorMethodInput { name: "layout", ty: AllocatorTy::Layout },
|
||||
|
|
@ -60,6 +75,7 @@ pub static ALLOCATOR_METHODS: &[AllocatorMethod] = &[
|
|||
},
|
||||
AllocatorMethod {
|
||||
name: sym::realloc,
|
||||
special: Some(SpecialAllocatorMethod::Realloc),
|
||||
inputs: &[
|
||||
AllocatorMethodInput { name: "ptr", ty: AllocatorTy::Ptr },
|
||||
AllocatorMethodInput { name: "layout", ty: AllocatorTy::Layout },
|
||||
|
|
@ -69,6 +85,7 @@ pub static ALLOCATOR_METHODS: &[AllocatorMethod] = &[
|
|||
},
|
||||
AllocatorMethod {
|
||||
name: sym::alloc_zeroed,
|
||||
special: Some(SpecialAllocatorMethod::AllocZeroed),
|
||||
inputs: &[AllocatorMethodInput { name: "layout", ty: AllocatorTy::Layout }],
|
||||
output: AllocatorTy::ResultPtr,
|
||||
},
|
||||
|
|
|
|||
|
|
@ -302,7 +302,7 @@ pub(crate) trait CombineAttributeParser<S: Stage>: 'static {
|
|||
type Item;
|
||||
/// A function that converts individual items (of type [`Item`](Self::Item)) into the final attribute.
|
||||
///
|
||||
/// For example, individual representations fomr `#[repr(...)]` attributes into an `AttributeKind::Repr(x)`,
|
||||
/// For example, individual representations from `#[repr(...)]` attributes into an `AttributeKind::Repr(x)`,
|
||||
/// where `x` is a vec of these individual reprs.
|
||||
const CONVERT: ConvertFn<Self::Item>;
|
||||
|
||||
|
|
|
|||
|
|
@ -28,7 +28,8 @@ pub fn parse_version(s: Symbol) -> Option<RustcVersion> {
|
|||
}
|
||||
|
||||
pub fn is_builtin_attr(attr: &impl AttributeExt) -> bool {
|
||||
attr.is_doc_comment() || attr.ident().is_some_and(|ident| is_builtin_attr_name(ident.name))
|
||||
attr.is_doc_comment().is_some()
|
||||
|| attr.ident().is_some_and(|ident| is_builtin_attr_name(ident.name))
|
||||
}
|
||||
|
||||
pub fn is_doc_alias_attrs_contain_symbol<'tcx, T: AttributeExt + 'tcx>(
|
||||
|
|
|
|||
|
|
@ -687,7 +687,7 @@ impl<'tcx> MirBorrowckCtxt<'_, '_, 'tcx> {
|
|||
}
|
||||
}
|
||||
|
||||
Some(Cause::DropVar(local, location)) => {
|
||||
Some(Cause::DropVar(local, location)) if !is_local_boring(local) => {
|
||||
let mut should_note_order = false;
|
||||
if self.local_name(local).is_some()
|
||||
&& let Some((WriteKind::StorageDeadOrDrop, place)) = kind_place
|
||||
|
|
@ -705,7 +705,7 @@ impl<'tcx> MirBorrowckCtxt<'_, '_, 'tcx> {
|
|||
}
|
||||
}
|
||||
|
||||
Some(Cause::LiveVar(..)) | None => {
|
||||
Some(Cause::LiveVar(..) | Cause::DropVar(..)) | None => {
|
||||
// Here, under NLL: no cause was found. Under polonius: no cause was found, or a
|
||||
// boring local was found, which we ignore like NLLs do to match its diagnostics.
|
||||
if let Some(region) = self.to_error_region_vid(borrow_region_vid) {
|
||||
|
|
|
|||
|
|
@ -71,6 +71,14 @@ fn expand_contract_clause(
|
|||
.span_err(attr_span, "contract annotations can only be used on functions"));
|
||||
}
|
||||
|
||||
// Contracts are not yet supported on async/gen functions
|
||||
if new_tts.iter().any(|tt| is_kw(tt, kw::Async) || is_kw(tt, kw::Gen)) {
|
||||
return Err(ecx.sess.dcx().span_err(
|
||||
attr_span,
|
||||
"contract annotations are not yet supported on async or gen functions",
|
||||
));
|
||||
}
|
||||
|
||||
// Found the `fn` keyword, now find either the `where` token or the function body.
|
||||
let next_tt = loop {
|
||||
let Some(tt) = cursor.next() else {
|
||||
|
|
|
|||
|
|
@ -1,13 +1,13 @@
|
|||
use libc::c_uint;
|
||||
use rustc_ast::expand::allocator::{
|
||||
AllocatorMethod, AllocatorTy, NO_ALLOC_SHIM_IS_UNSTABLE, default_fn_name, global_fn_name,
|
||||
AllocatorMethod, AllocatorTy, NO_ALLOC_SHIM_IS_UNSTABLE, SpecialAllocatorMethod,
|
||||
default_fn_name, global_fn_name,
|
||||
};
|
||||
use rustc_codegen_ssa::traits::BaseTypeCodegenMethods as _;
|
||||
use rustc_middle::bug;
|
||||
use rustc_middle::middle::codegen_fn_attrs::{CodegenFnAttrFlags, CodegenFnAttrs};
|
||||
use rustc_middle::ty::TyCtxt;
|
||||
use rustc_session::config::{DebugInfo, OomStrategy};
|
||||
use rustc_span::sym;
|
||||
use rustc_symbol_mangling::mangle_internal_symbol;
|
||||
|
||||
use crate::attributes::llfn_attrs_from_instance;
|
||||
|
|
@ -65,12 +65,12 @@ pub(crate) unsafe fn codegen(
|
|||
let from_name = mangle_internal_symbol(tcx, &global_fn_name(method.name));
|
||||
let to_name = mangle_internal_symbol(tcx, &default_fn_name(method.name));
|
||||
|
||||
let alloc_attr_flag = match method.name {
|
||||
sym::alloc => CodegenFnAttrFlags::ALLOCATOR,
|
||||
sym::dealloc => CodegenFnAttrFlags::DEALLOCATOR,
|
||||
sym::realloc => CodegenFnAttrFlags::REALLOCATOR,
|
||||
sym::alloc_zeroed => CodegenFnAttrFlags::ALLOCATOR_ZEROED,
|
||||
_ => CodegenFnAttrFlags::empty(),
|
||||
let alloc_attr_flag = match method.special {
|
||||
Some(SpecialAllocatorMethod::Alloc) => CodegenFnAttrFlags::ALLOCATOR,
|
||||
Some(SpecialAllocatorMethod::Dealloc) => CodegenFnAttrFlags::DEALLOCATOR,
|
||||
Some(SpecialAllocatorMethod::Realloc) => CodegenFnAttrFlags::REALLOCATOR,
|
||||
Some(SpecialAllocatorMethod::AllocZeroed) => CodegenFnAttrFlags::ALLOCATOR_ZEROED,
|
||||
None => CodegenFnAttrFlags::empty(),
|
||||
};
|
||||
|
||||
let mut attrs = CodegenFnAttrs::new();
|
||||
|
|
|
|||
|
|
@ -669,6 +669,7 @@ pub fn allocator_shim_contents(tcx: TyCtxt<'_>, kind: AllocatorKind) -> Vec<Allo
|
|||
if tcx.alloc_error_handler_kind(()).unwrap() == AllocatorKind::Default {
|
||||
methods.push(AllocatorMethod {
|
||||
name: ALLOC_ERROR_HANDLER,
|
||||
special: None,
|
||||
inputs: &[],
|
||||
output: AllocatorTy::Never,
|
||||
});
|
||||
|
|
|
|||
|
|
@ -289,7 +289,7 @@ enum NodeState<N, S, A: Annotation> {
|
|||
#[derive(Copy, Clone, Debug)]
|
||||
enum WalkReturn<S, A: Annotation> {
|
||||
/// The walk found a cycle, but the entire component is not known to have
|
||||
/// been fully walked yet. We only know the minimum depth of this
|
||||
/// been fully walked yet. We only know the minimum depth of this
|
||||
/// component in a minimum spanning tree of the graph. This component
|
||||
/// is tentatively represented by the state of the first node of this
|
||||
/// cycle we met, which is at `min_depth`.
|
||||
|
|
|
|||
|
|
@ -1304,8 +1304,12 @@ impl AttributeExt for Attribute {
|
|||
}
|
||||
|
||||
#[inline]
|
||||
fn is_doc_comment(&self) -> bool {
|
||||
matches!(self, Attribute::Parsed(AttributeKind::DocComment { .. }))
|
||||
fn is_doc_comment(&self) -> Option<Span> {
|
||||
if let Attribute::Parsed(AttributeKind::DocComment { span, .. }) = self {
|
||||
Some(*span)
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
|
|
@ -1423,7 +1427,7 @@ impl Attribute {
|
|||
}
|
||||
|
||||
#[inline]
|
||||
pub fn is_doc_comment(&self) -> bool {
|
||||
pub fn is_doc_comment(&self) -> Option<Span> {
|
||||
AttributeExt::is_doc_comment(self)
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1651,9 +1651,7 @@ fn check_method_receiver<'tcx>(
|
|||
|
||||
// If the receiver already has errors reported, consider it valid to avoid
|
||||
// unnecessary errors (#58712).
|
||||
if receiver_ty.references_error() {
|
||||
return Ok(());
|
||||
}
|
||||
receiver_ty.error_reported()?;
|
||||
|
||||
let arbitrary_self_types_level = if tcx.features().arbitrary_self_types_pointers() {
|
||||
Some(ArbitrarySelfTypesLevel::WithPointers)
|
||||
|
|
|
|||
|
|
@ -39,9 +39,7 @@ fn check_impl<'tcx>(
|
|||
|
||||
// Skip impls where one of the self type is an error type.
|
||||
// This occurs with e.g., resolve failures (#30589).
|
||||
if trait_ref.references_error() {
|
||||
return Ok(());
|
||||
}
|
||||
trait_ref.error_reported()?;
|
||||
|
||||
enforce_trait_manually_implementable(tcx, impl_def_id, trait_ref.def_id, trait_def)
|
||||
.and(enforce_empty_impls_for_marker_traits(tcx, impl_def_id, trait_ref.def_id, trait_def))
|
||||
|
|
@ -188,9 +186,9 @@ fn check_object_overlap<'tcx>(
|
|||
) -> Result<(), ErrorGuaranteed> {
|
||||
let trait_def_id = trait_ref.def_id;
|
||||
|
||||
if trait_ref.references_error() {
|
||||
if let Err(guar) = trait_ref.error_reported() {
|
||||
debug!("coherence: skipping impl {:?} with error {:?}", impl_def_id, trait_ref);
|
||||
return Ok(());
|
||||
return Err(guar);
|
||||
}
|
||||
|
||||
// check for overlap with the automatic `impl Trait for dyn Trait`
|
||||
|
|
|
|||
|
|
@ -76,20 +76,10 @@ pub(crate) fn enforce_impl_lifetime_params_are_constrained(
|
|||
impl_def_id: LocalDefId,
|
||||
) -> Result<(), ErrorGuaranteed> {
|
||||
let impl_self_ty = tcx.type_of(impl_def_id).instantiate_identity();
|
||||
if impl_self_ty.references_error() {
|
||||
// Don't complain about unconstrained type params when self ty isn't known due to errors.
|
||||
// (#36836)
|
||||
tcx.dcx().span_delayed_bug(
|
||||
tcx.def_span(impl_def_id),
|
||||
format!(
|
||||
"potentially unconstrained type parameters weren't evaluated: {impl_self_ty:?}",
|
||||
),
|
||||
);
|
||||
// This is super fishy, but our current `rustc_hir_analysis::check_crate` pipeline depends on
|
||||
// `type_of` having been called much earlier, and thus this value being read from cache.
|
||||
// Compilation must continue in order for other important diagnostics to keep showing up.
|
||||
return Ok(());
|
||||
}
|
||||
|
||||
// Don't complain about unconstrained type params when self ty isn't known due to errors.
|
||||
// (#36836)
|
||||
impl_self_ty.error_reported()?;
|
||||
|
||||
let impl_generics = tcx.generics_of(impl_def_id);
|
||||
let impl_predicates = tcx.predicates_of(impl_def_id);
|
||||
|
|
@ -174,20 +164,11 @@ pub(crate) fn enforce_impl_non_lifetime_params_are_constrained(
|
|||
impl_def_id: LocalDefId,
|
||||
) -> Result<(), ErrorGuaranteed> {
|
||||
let impl_self_ty = tcx.type_of(impl_def_id).instantiate_identity();
|
||||
if impl_self_ty.references_error() {
|
||||
// Don't complain about unconstrained type params when self ty isn't known due to errors.
|
||||
// (#36836)
|
||||
tcx.dcx().span_delayed_bug(
|
||||
tcx.def_span(impl_def_id),
|
||||
format!(
|
||||
"potentially unconstrained type parameters weren't evaluated: {impl_self_ty:?}",
|
||||
),
|
||||
);
|
||||
// This is super fishy, but our current `rustc_hir_analysis::check_crate` pipeline depends on
|
||||
// `type_of` having been called much earlier, and thus this value being read from cache.
|
||||
// Compilation must continue in order for other important diagnostics to keep showing up.
|
||||
return Ok(());
|
||||
}
|
||||
|
||||
// Don't complain about unconstrained type params when self ty isn't known due to errors.
|
||||
// (#36836)
|
||||
impl_self_ty.error_reported()?;
|
||||
|
||||
let impl_generics = tcx.generics_of(impl_def_id);
|
||||
let impl_predicates = tcx.predicates_of(impl_def_id);
|
||||
let impl_trait_ref = tcx.impl_trait_ref(impl_def_id).map(ty::EarlyBinder::instantiate_identity);
|
||||
|
|
|
|||
|
|
@ -685,9 +685,11 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||
});
|
||||
let ty =
|
||||
self.check_expr_with_expectation_and_needs(oprnd, hint, Needs::maybe_mut_place(mutbl));
|
||||
if let Err(guar) = ty.error_reported() {
|
||||
return Ty::new_error(self.tcx, guar);
|
||||
}
|
||||
|
||||
match kind {
|
||||
_ if ty.references_error() => Ty::new_misc_error(self.tcx),
|
||||
hir::BorrowKind::Raw => {
|
||||
self.check_named_place_expr(oprnd);
|
||||
Ty::new_ptr(self.tcx, ty, mutbl)
|
||||
|
|
|
|||
|
|
@ -393,7 +393,7 @@ pub struct MissingDoc;
|
|||
impl_lint_pass!(MissingDoc => [MISSING_DOCS]);
|
||||
|
||||
fn has_doc(attr: &hir::Attribute) -> bool {
|
||||
if attr.is_doc_comment() {
|
||||
if attr.is_doc_comment().is_some() {
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -6,6 +6,7 @@ use rustc_errors::ErrorGuaranteed;
|
|||
use rustc_hir::def_id::DefId;
|
||||
use rustc_macros::{HashStable, TypeVisitable};
|
||||
use rustc_query_system::cache::Cache;
|
||||
use rustc_type_ir::solve::AliasBoundKind;
|
||||
|
||||
use self::EvaluationResult::*;
|
||||
use super::{SelectionError, SelectionResult};
|
||||
|
|
@ -116,8 +117,13 @@ pub enum SelectionCandidate<'tcx> {
|
|||
|
||||
/// This is a trait matching with a projected type as `Self`, and we found
|
||||
/// an applicable bound in the trait definition. The `usize` is an index
|
||||
/// into the list returned by `tcx.item_bounds`.
|
||||
ProjectionCandidate(usize),
|
||||
/// into the list returned by `tcx.item_bounds` and the `AliasBoundKind`
|
||||
/// is whether this is candidate from recursion on the self type of a
|
||||
/// projection.
|
||||
ProjectionCandidate {
|
||||
idx: usize,
|
||||
kind: AliasBoundKind,
|
||||
},
|
||||
|
||||
/// Implementation of a `Fn`-family trait by one of the anonymous types
|
||||
/// generated for an `||` expression.
|
||||
|
|
|
|||
|
|
@ -521,6 +521,10 @@ impl<'tcx> Interner for TyCtxt<'tcx> {
|
|||
self.is_default_trait(def_id)
|
||||
}
|
||||
|
||||
fn is_sizedness_trait(self, def_id: DefId) -> bool {
|
||||
self.is_sizedness_trait(def_id)
|
||||
}
|
||||
|
||||
fn as_lang_item(self, def_id: DefId) -> Option<SolverLangItem> {
|
||||
lang_item_to_solver_lang_item(self.lang_items().from_def_id(def_id)?)
|
||||
}
|
||||
|
|
@ -1787,6 +1791,10 @@ impl<'tcx> TyCtxt<'tcx> {
|
|||
.any(|&default_trait| self.lang_items().get(default_trait) == Some(def_id))
|
||||
}
|
||||
|
||||
pub fn is_sizedness_trait(self, def_id: DefId) -> bool {
|
||||
matches!(self.as_lang_item(def_id), Some(LangItem::Sized | LangItem::MetaSized))
|
||||
}
|
||||
|
||||
/// Returns a range of the start/end indices specified with the
|
||||
/// `rustc_layout_scalar_valid_range` attribute.
|
||||
// FIXME(eddyb) this is an awkward spot for this method, maybe move it?
|
||||
|
|
|
|||
|
|
@ -59,7 +59,7 @@ pub use rustc_type_ir::fast_reject::DeepRejectCtxt;
|
|||
)]
|
||||
use rustc_type_ir::inherent;
|
||||
pub use rustc_type_ir::relate::VarianceDiagInfo;
|
||||
pub use rustc_type_ir::solve::SizedTraitKind;
|
||||
pub use rustc_type_ir::solve::{CandidatePreferenceMode, SizedTraitKind};
|
||||
pub use rustc_type_ir::*;
|
||||
#[allow(hidden_glob_reexports, unused_imports)]
|
||||
use rustc_type_ir::{InferCtxtLike, Interner};
|
||||
|
|
|
|||
|
|
@ -31,6 +31,7 @@ use crate::ty::{
|
|||
|
||||
thread_local! {
|
||||
static FORCE_IMPL_FILENAME_LINE: Cell<bool> = const { Cell::new(false) };
|
||||
static SHOULD_PREFIX_WITH_CRATE_NAME: Cell<bool> = const { Cell::new(false) };
|
||||
static SHOULD_PREFIX_WITH_CRATE: Cell<bool> = const { Cell::new(false) };
|
||||
static NO_TRIMMED_PATH: Cell<bool> = const { Cell::new(false) };
|
||||
static FORCE_TRIMMED_PATH: Cell<bool> = const { Cell::new(false) };
|
||||
|
|
@ -98,7 +99,18 @@ define_helper!(
|
|||
/// cycle errors, this can result in extra or suboptimal error output,
|
||||
/// so this variable disables that check.
|
||||
fn with_forced_impl_filename_line(ForcedImplGuard, FORCE_IMPL_FILENAME_LINE);
|
||||
/// Adds the crate name prefix to paths where appropriate.
|
||||
/// Unlike `with_crate_prefix`, this unconditionally uses `tcx.crate_name` instead of sometimes
|
||||
/// using `crate::` for local items.
|
||||
///
|
||||
/// Overrides `with_crate_prefix`.
|
||||
|
||||
// This function is not currently used in-tree, but it's used by a downstream rustc-driver in
|
||||
// Ferrocene. Please check with them before removing it.
|
||||
fn with_resolve_crate_name(CrateNamePrefixGuard, SHOULD_PREFIX_WITH_CRATE_NAME);
|
||||
/// Adds the `crate::` prefix to paths where appropriate.
|
||||
///
|
||||
/// Ignored if `with_resolve_crate_name` is active.
|
||||
fn with_crate_prefix(CratePrefixGuard, SHOULD_PREFIX_WITH_CRATE);
|
||||
/// Prevent path trimming if it is turned on. Path trimming affects `Display` impl
|
||||
/// of various rustc types, for example `std::vec::Vec` would be trimmed to `Vec`,
|
||||
|
|
@ -2313,7 +2325,7 @@ impl<'tcx> Printer<'tcx> for FmtPrinter<'_, 'tcx> {
|
|||
|
||||
fn print_crate_name(&mut self, cnum: CrateNum) -> Result<(), PrintError> {
|
||||
self.empty_path = true;
|
||||
if cnum == LOCAL_CRATE {
|
||||
if cnum == LOCAL_CRATE && !with_resolve_crate_name() {
|
||||
if self.tcx.sess.at_least_rust_2018() {
|
||||
// We add the `crate::` keyword on Rust 2018, only when desired.
|
||||
if with_crate_prefix() {
|
||||
|
|
|
|||
|
|
@ -9,7 +9,7 @@ use derive_where::derive_where;
|
|||
use rustc_type_ir::inherent::*;
|
||||
use rustc_type_ir::lang_items::SolverTraitLangItem;
|
||||
use rustc_type_ir::search_graph::CandidateHeadUsages;
|
||||
use rustc_type_ir::solve::SizedTraitKind;
|
||||
use rustc_type_ir::solve::{AliasBoundKind, SizedTraitKind};
|
||||
use rustc_type_ir::{
|
||||
self as ty, Interner, TypeFlags, TypeFoldable, TypeFolder, TypeSuperFoldable,
|
||||
TypeSuperVisitable, TypeVisitable, TypeVisitableExt, TypeVisitor, TypingMode, Upcast,
|
||||
|
|
@ -27,11 +27,6 @@ use crate::solve::{
|
|||
has_no_inference_or_external_constraints,
|
||||
};
|
||||
|
||||
enum AliasBoundKind {
|
||||
SelfBounds,
|
||||
NonSelfBounds,
|
||||
}
|
||||
|
||||
/// A candidate is a possible way to prove a goal.
|
||||
///
|
||||
/// It consists of both the `source`, which describes how that goal would be proven,
|
||||
|
|
@ -451,7 +446,7 @@ where
|
|||
matches!(
|
||||
c.source,
|
||||
CandidateSource::ParamEnv(ParamEnvSource::NonGlobal)
|
||||
| CandidateSource::AliasBound
|
||||
| CandidateSource::AliasBound(_)
|
||||
) && has_no_inference_or_external_constraints(c.result)
|
||||
})
|
||||
{
|
||||
|
|
@ -711,7 +706,7 @@ where
|
|||
self.evaluate_added_goals_and_make_canonical_response(Certainty::AMBIGUOUS)
|
||||
{
|
||||
candidates.push(Candidate {
|
||||
source: CandidateSource::AliasBound,
|
||||
source: CandidateSource::AliasBound(consider_self_bounds),
|
||||
result,
|
||||
head_usages: CandidateHeadUsages::default(),
|
||||
});
|
||||
|
|
@ -735,7 +730,7 @@ where
|
|||
{
|
||||
candidates.extend(G::probe_and_consider_implied_clause(
|
||||
self,
|
||||
CandidateSource::AliasBound,
|
||||
CandidateSource::AliasBound(consider_self_bounds),
|
||||
goal,
|
||||
assumption,
|
||||
[],
|
||||
|
|
@ -750,7 +745,7 @@ where
|
|||
{
|
||||
candidates.extend(G::probe_and_consider_implied_clause(
|
||||
self,
|
||||
CandidateSource::AliasBound,
|
||||
CandidateSource::AliasBound(consider_self_bounds),
|
||||
goal,
|
||||
assumption,
|
||||
[],
|
||||
|
|
@ -1030,7 +1025,7 @@ where
|
|||
item_bound.fold_with(&mut ReplaceOpaque { cx: self.cx(), alias_ty, self_ty });
|
||||
candidates.extend(G::probe_and_match_goal_against_assumption(
|
||||
self,
|
||||
CandidateSource::AliasBound,
|
||||
CandidateSource::AliasBound(AliasBoundKind::SelfBounds),
|
||||
goal,
|
||||
assumption,
|
||||
|ecx| {
|
||||
|
|
|
|||
|
|
@ -4,8 +4,8 @@
|
|||
use rustc_type_ir::fast_reject::DeepRejectCtxt;
|
||||
use rustc_type_ir::inherent::*;
|
||||
use rustc_type_ir::lang_items::SolverTraitLangItem;
|
||||
use rustc_type_ir::solve::SizedTraitKind;
|
||||
use rustc_type_ir::solve::inspect::ProbeKind;
|
||||
use rustc_type_ir::solve::{AliasBoundKind, SizedTraitKind};
|
||||
use rustc_type_ir::{self as ty, Interner, TypingMode, elaborate};
|
||||
use tracing::instrument;
|
||||
|
||||
|
|
@ -96,7 +96,7 @@ where
|
|||
) {
|
||||
candidates.extend(Self::probe_and_match_goal_against_assumption(
|
||||
ecx,
|
||||
CandidateSource::AliasBound,
|
||||
CandidateSource::AliasBound(AliasBoundKind::SelfBounds),
|
||||
goal,
|
||||
clause,
|
||||
|ecx| {
|
||||
|
|
|
|||
|
|
@ -4,7 +4,9 @@ use rustc_type_ir::data_structures::IndexSet;
|
|||
use rustc_type_ir::fast_reject::DeepRejectCtxt;
|
||||
use rustc_type_ir::inherent::*;
|
||||
use rustc_type_ir::lang_items::SolverTraitLangItem;
|
||||
use rustc_type_ir::solve::{CanonicalResponse, SizedTraitKind};
|
||||
use rustc_type_ir::solve::{
|
||||
AliasBoundKind, CandidatePreferenceMode, CanonicalResponse, SizedTraitKind,
|
||||
};
|
||||
use rustc_type_ir::{
|
||||
self as ty, Interner, Movability, PredicatePolarity, TraitPredicate, TraitRef,
|
||||
TypeVisitableExt as _, TypingMode, Upcast as _, elaborate,
|
||||
|
|
@ -1355,6 +1357,7 @@ where
|
|||
#[instrument(level = "debug", skip(self), ret)]
|
||||
pub(super) fn merge_trait_candidates(
|
||||
&mut self,
|
||||
candidate_preference_mode: CandidatePreferenceMode,
|
||||
mut candidates: Vec<Candidate<I>>,
|
||||
failed_candidate_info: FailedCandidateInfo,
|
||||
) -> Result<(CanonicalResponse<I>, Option<TraitGoalProvenVia>), NoSolution> {
|
||||
|
|
@ -1380,6 +1383,23 @@ where
|
|||
return Ok((candidate.result, Some(TraitGoalProvenVia::Misc)));
|
||||
}
|
||||
|
||||
// Extract non-nested alias bound candidates, will be preferred over where bounds if
|
||||
// we're proving an auto-trait, sizedness trait or default trait.
|
||||
if matches!(candidate_preference_mode, CandidatePreferenceMode::Marker)
|
||||
&& candidates.iter().any(|c| {
|
||||
matches!(c.source, CandidateSource::AliasBound(AliasBoundKind::SelfBounds))
|
||||
})
|
||||
{
|
||||
let alias_bounds: Vec<_> = candidates
|
||||
.extract_if(.., |c| matches!(c.source, CandidateSource::AliasBound(..)))
|
||||
.collect();
|
||||
return if let Some((response, _)) = self.try_merge_candidates(&alias_bounds) {
|
||||
Ok((response, Some(TraitGoalProvenVia::AliasBound)))
|
||||
} else {
|
||||
Ok((self.bail_with_ambiguity(&alias_bounds), None))
|
||||
};
|
||||
}
|
||||
|
||||
// If there are non-global where-bounds, prefer where-bounds
|
||||
// (including global ones) over everything else.
|
||||
let has_non_global_where_bounds = candidates
|
||||
|
|
@ -1427,9 +1447,10 @@ where
|
|||
};
|
||||
}
|
||||
|
||||
if candidates.iter().any(|c| matches!(c.source, CandidateSource::AliasBound)) {
|
||||
// Next, prefer any alias bound (nested or otherwise).
|
||||
if candidates.iter().any(|c| matches!(c.source, CandidateSource::AliasBound(_))) {
|
||||
let alias_bounds: Vec<_> = candidates
|
||||
.extract_if(.., |c| matches!(c.source, CandidateSource::AliasBound))
|
||||
.extract_if(.., |c| matches!(c.source, CandidateSource::AliasBound(_)))
|
||||
.collect();
|
||||
return if let Some((response, _)) = self.try_merge_candidates(&alias_bounds) {
|
||||
Ok((response, Some(TraitGoalProvenVia::AliasBound)))
|
||||
|
|
@ -1470,7 +1491,9 @@ where
|
|||
) -> Result<(CanonicalResponse<I>, Option<TraitGoalProvenVia>), NoSolution> {
|
||||
let (candidates, failed_candidate_info) =
|
||||
self.assemble_and_evaluate_candidates(goal, AssembleCandidatesFrom::All);
|
||||
self.merge_trait_candidates(candidates, failed_candidate_info)
|
||||
let candidate_preference_mode =
|
||||
CandidatePreferenceMode::compute(self.cx(), goal.predicate.def_id());
|
||||
self.merge_trait_candidates(candidate_preference_mode, candidates, failed_candidate_info)
|
||||
}
|
||||
|
||||
fn try_stall_coroutine(&mut self, self_ty: I::Ty) -> Option<Result<Candidate<I>, NoSolution>> {
|
||||
|
|
|
|||
|
|
@ -22,7 +22,7 @@ impl<'a> HashStable<StableHashingContext<'a>> for [hir::Attribute] {
|
|||
let filtered: SmallVec<[&hir::Attribute; 8]> = self
|
||||
.iter()
|
||||
.filter(|attr| {
|
||||
!attr.is_doc_comment()
|
||||
attr.is_doc_comment().is_none()
|
||||
// FIXME(jdonszelmann) have a better way to handle ignored attrs
|
||||
&& !attr.ident().is_some_and(|ident| hcx.is_ignored_attr(ident.name))
|
||||
})
|
||||
|
|
|
|||
|
|
@ -216,8 +216,7 @@ pub fn attrs_to_doc_fragments<'a, A: AttributeExt + Clone + 'a>(
|
|||
for (attr, item_id) in attrs {
|
||||
if let Some((doc_str, comment_kind)) = attr.doc_str_and_comment_kind() {
|
||||
let doc = beautify_doc_string(doc_str, comment_kind);
|
||||
let (span, kind, from_expansion) = if attr.is_doc_comment() {
|
||||
let span = attr.span();
|
||||
let (span, kind, from_expansion) = if let Some(span) = attr.is_doc_comment() {
|
||||
(span, DocFragmentKind::SugaredDoc, span.from_expansion())
|
||||
} else {
|
||||
let attr_span = attr.span();
|
||||
|
|
|
|||
|
|
@ -21,7 +21,7 @@ bitflags! {
|
|||
const GENERALIZE_REPR_C = 2;
|
||||
/// Normalizes integers for compatibility with Clang
|
||||
/// `-fsanitize-cfi-icall-experimental-normalize-integers` option for cross-language LLVM
|
||||
/// CFI and KCFI support.
|
||||
/// CFI and KCFI support.
|
||||
const NORMALIZE_INTEGERS = 4;
|
||||
/// Do not perform self type erasure for attaching a secondary type id to methods with their
|
||||
/// concrete self so they can be used as function pointers.
|
||||
|
|
|
|||
|
|
@ -309,7 +309,7 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
|
|||
pub struct OnUnimplementedFormatString {
|
||||
/// Symbol of the format string, i.e. `"content"`
|
||||
symbol: Symbol,
|
||||
///The span of the format string, i.e. `"content"`
|
||||
/// The span of the format string, i.e. `"content"`
|
||||
span: Span,
|
||||
is_diagnostic_namespace_variant: bool,
|
||||
}
|
||||
|
|
|
|||
|
|
@ -126,7 +126,9 @@ fn candidate_should_be_dropped_in_favor_of<'tcx>(
|
|||
// Prefer dyn candidates over non-dyn candidates. This is necessary to
|
||||
// handle the unsoundness between `impl<T: ?Sized> Any for T` and `dyn Any: Any`.
|
||||
(
|
||||
CandidateSource::Impl(_) | CandidateSource::ParamEnv(_) | CandidateSource::AliasBound,
|
||||
CandidateSource::Impl(_)
|
||||
| CandidateSource::ParamEnv(_)
|
||||
| CandidateSource::AliasBound(_),
|
||||
CandidateSource::BuiltinImpl(BuiltinImplSource::Object { .. }),
|
||||
) => true,
|
||||
|
||||
|
|
@ -175,7 +177,9 @@ fn to_selection<'tcx>(
|
|||
})
|
||||
}
|
||||
CandidateSource::BuiltinImpl(builtin) => ImplSource::Builtin(builtin, nested),
|
||||
CandidateSource::ParamEnv(_) | CandidateSource::AliasBound => ImplSource::Param(nested),
|
||||
CandidateSource::ParamEnv(_) | CandidateSource::AliasBound(_) => {
|
||||
ImplSource::Param(nested)
|
||||
}
|
||||
CandidateSource::CoherenceUnknowable => {
|
||||
span_bug!(span, "didn't expect to select an unknowable candidate")
|
||||
}
|
||||
|
|
|
|||
|
|
@ -741,7 +741,7 @@ fn assemble_candidates_from_trait_def<'cx, 'tcx>(
|
|||
let mut ambiguous = false;
|
||||
let _ = selcx.for_each_item_bound(
|
||||
obligation.predicate.self_ty(),
|
||||
|selcx, clause, _| {
|
||||
|selcx, clause, _, _| {
|
||||
let Some(clause) = clause.as_projection_clause() else {
|
||||
return ControlFlow::Continue(());
|
||||
};
|
||||
|
|
|
|||
|
|
@ -208,7 +208,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
|
|||
let mut distinct_normalized_bounds = FxHashSet::default();
|
||||
let _ = self.for_each_item_bound::<!>(
|
||||
placeholder_trait_predicate.self_ty(),
|
||||
|selcx, bound, idx| {
|
||||
|selcx, bound, idx, alias_bound_kind| {
|
||||
let Some(bound) = bound.as_trait_clause() else {
|
||||
return ControlFlow::Continue(());
|
||||
};
|
||||
|
|
@ -230,12 +230,16 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
|
|||
bound.map_bound(|pred| pred.trait_ref),
|
||||
) {
|
||||
Ok(None) => {
|
||||
candidates.vec.push(ProjectionCandidate(idx));
|
||||
candidates
|
||||
.vec
|
||||
.push(ProjectionCandidate { idx, kind: alias_bound_kind });
|
||||
}
|
||||
Ok(Some(normalized_trait))
|
||||
if distinct_normalized_bounds.insert(normalized_trait) =>
|
||||
{
|
||||
candidates.vec.push(ProjectionCandidate(idx));
|
||||
candidates
|
||||
.vec
|
||||
.push(ProjectionCandidate { idx, kind: alias_bound_kind });
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
|
|
@ -825,7 +829,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
|
|||
}
|
||||
|
||||
ty::Alias(ty::Opaque, alias) => {
|
||||
if candidates.vec.iter().any(|c| matches!(c, ProjectionCandidate(_))) {
|
||||
if candidates.vec.iter().any(|c| matches!(c, ProjectionCandidate { .. })) {
|
||||
// We do not generate an auto impl candidate for `impl Trait`s which already
|
||||
// reference our auto trait.
|
||||
//
|
||||
|
|
|
|||
|
|
@ -67,7 +67,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
|
|||
ImplSource::Builtin(BuiltinImplSource::Misc, data)
|
||||
}
|
||||
|
||||
ProjectionCandidate(idx) => {
|
||||
ProjectionCandidate { idx, .. } => {
|
||||
let obligations = self.confirm_projection_candidate(obligation, idx)?;
|
||||
ImplSource::Param(obligations)
|
||||
}
|
||||
|
|
@ -144,15 +144,13 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
|
|||
obligation: &PolyTraitObligation<'tcx>,
|
||||
idx: usize,
|
||||
) -> Result<PredicateObligations<'tcx>, SelectionError<'tcx>> {
|
||||
let tcx = self.tcx();
|
||||
|
||||
let placeholder_trait_predicate =
|
||||
self.infcx.enter_forall_and_leak_universe(obligation.predicate).trait_ref;
|
||||
let placeholder_self_ty = self.infcx.shallow_resolve(placeholder_trait_predicate.self_ty());
|
||||
let candidate_predicate = self
|
||||
.for_each_item_bound(
|
||||
placeholder_self_ty,
|
||||
|_, clause, clause_idx| {
|
||||
|_, clause, clause_idx, _| {
|
||||
if clause_idx == idx {
|
||||
ControlFlow::Break(clause)
|
||||
} else {
|
||||
|
|
@ -194,28 +192,6 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
|
|||
.map_err(|_| SelectionError::Unimplemented)?,
|
||||
);
|
||||
|
||||
// FIXME(compiler-errors): I don't think this is needed.
|
||||
if let ty::Alias(ty::Projection, alias_ty) = placeholder_self_ty.kind() {
|
||||
let predicates = tcx.predicates_of(alias_ty.def_id).instantiate_own(tcx, alias_ty.args);
|
||||
for (predicate, _) in predicates {
|
||||
let normalized = normalize_with_depth_to(
|
||||
self,
|
||||
obligation.param_env,
|
||||
obligation.cause.clone(),
|
||||
obligation.recursion_depth + 1,
|
||||
predicate,
|
||||
&mut obligations,
|
||||
);
|
||||
obligations.push(Obligation::with_depth(
|
||||
self.tcx(),
|
||||
obligation.cause.clone(),
|
||||
obligation.recursion_depth + 1,
|
||||
obligation.param_env,
|
||||
normalized,
|
||||
));
|
||||
}
|
||||
}
|
||||
|
||||
Ok(obligations)
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -28,9 +28,11 @@ use rustc_middle::ty::abstract_const::NotConstEvaluatable;
|
|||
use rustc_middle::ty::error::TypeErrorToStringExt;
|
||||
use rustc_middle::ty::print::{PrintTraitRefExt as _, with_no_trimmed_paths};
|
||||
use rustc_middle::ty::{
|
||||
self, DeepRejectCtxt, GenericArgsRef, PolyProjectionPredicate, SizedTraitKind, Ty, TyCtxt,
|
||||
TypeFoldable, TypeVisitableExt, TypingMode, Upcast, elaborate, may_use_unstable_feature,
|
||||
self, CandidatePreferenceMode, DeepRejectCtxt, GenericArgsRef, PolyProjectionPredicate,
|
||||
SizedTraitKind, Ty, TyCtxt, TypeFoldable, TypeVisitableExt, TypingMode, Upcast, elaborate,
|
||||
may_use_unstable_feature,
|
||||
};
|
||||
use rustc_next_trait_solver::solve::AliasBoundKind;
|
||||
use rustc_span::{Symbol, sym};
|
||||
use tracing::{debug, instrument, trace};
|
||||
|
||||
|
|
@ -474,7 +476,11 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
|
|||
}
|
||||
} else {
|
||||
let has_non_region_infer = stack.obligation.predicate.has_non_region_infer();
|
||||
if let Some(candidate) = self.winnow_candidates(has_non_region_infer, candidates) {
|
||||
let candidate_preference_mode =
|
||||
CandidatePreferenceMode::compute(self.tcx(), stack.obligation.predicate.def_id());
|
||||
if let Some(candidate) =
|
||||
self.winnow_candidates(has_non_region_infer, candidate_preference_mode, candidates)
|
||||
{
|
||||
self.filter_reservation_impls(candidate)
|
||||
} else {
|
||||
Ok(None)
|
||||
|
|
@ -1623,11 +1629,16 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
|
|||
pub(super) fn for_each_item_bound<T>(
|
||||
&mut self,
|
||||
mut self_ty: Ty<'tcx>,
|
||||
mut for_each: impl FnMut(&mut Self, ty::Clause<'tcx>, usize) -> ControlFlow<T, ()>,
|
||||
mut for_each: impl FnMut(
|
||||
&mut Self,
|
||||
ty::Clause<'tcx>,
|
||||
usize,
|
||||
AliasBoundKind,
|
||||
) -> ControlFlow<T, ()>,
|
||||
on_ambiguity: impl FnOnce(),
|
||||
) -> ControlFlow<T, ()> {
|
||||
let mut idx = 0;
|
||||
let mut in_parent_alias_type = false;
|
||||
let mut alias_bound_kind = AliasBoundKind::SelfBounds;
|
||||
|
||||
loop {
|
||||
let (kind, alias_ty) = match *self_ty.kind() {
|
||||
|
|
@ -1643,14 +1654,14 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
|
|||
// share the same type as `self_ty`. This is because for truly rigid
|
||||
// projections, we will never be able to equate, e.g. `<T as Tr>::A`
|
||||
// with `<<T as Tr>::A as Tr>::A`.
|
||||
let relevant_bounds = if in_parent_alias_type {
|
||||
let relevant_bounds = if matches!(alias_bound_kind, AliasBoundKind::NonSelfBounds) {
|
||||
self.tcx().item_non_self_bounds(alias_ty.def_id)
|
||||
} else {
|
||||
self.tcx().item_self_bounds(alias_ty.def_id)
|
||||
};
|
||||
|
||||
for bound in relevant_bounds.instantiate(self.tcx(), alias_ty.args) {
|
||||
for_each(self, bound, idx)?;
|
||||
for_each(self, bound, idx, alias_bound_kind)?;
|
||||
idx += 1;
|
||||
}
|
||||
|
||||
|
|
@ -1660,7 +1671,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
|
|||
return ControlFlow::Continue(());
|
||||
}
|
||||
|
||||
in_parent_alias_type = true;
|
||||
alias_bound_kind = AliasBoundKind::NonSelfBounds;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -1821,6 +1832,7 @@ impl<'tcx> SelectionContext<'_, 'tcx> {
|
|||
fn winnow_candidates(
|
||||
&mut self,
|
||||
has_non_region_infer: bool,
|
||||
candidate_preference_mode: CandidatePreferenceMode,
|
||||
mut candidates: Vec<EvaluatedCandidate<'tcx>>,
|
||||
) -> Option<SelectionCandidate<'tcx>> {
|
||||
if candidates.len() == 1 {
|
||||
|
|
@ -1874,6 +1886,29 @@ impl<'tcx> SelectionContext<'_, 'tcx> {
|
|||
break;
|
||||
}
|
||||
|
||||
let mut alias_bounds = candidates.iter().filter_map(|c| {
|
||||
if let ProjectionCandidate { idx, kind } = c.candidate {
|
||||
Some((idx, kind))
|
||||
} else {
|
||||
None
|
||||
}
|
||||
});
|
||||
// Extract non-nested alias bound candidates, will be preferred over where bounds if
|
||||
// we're proving an auto-trait, sizedness trait or default trait.
|
||||
if matches!(candidate_preference_mode, CandidatePreferenceMode::Marker) {
|
||||
match alias_bounds
|
||||
.clone()
|
||||
.filter_map(|(idx, kind)| (kind == AliasBoundKind::SelfBounds).then_some(idx))
|
||||
.try_reduce(|c1, c2| if has_non_region_infer { None } else { Some(c1.min(c2)) })
|
||||
{
|
||||
Some(Some(idx)) => {
|
||||
return Some(ProjectionCandidate { idx, kind: AliasBoundKind::SelfBounds });
|
||||
}
|
||||
Some(None) => {}
|
||||
None => return None,
|
||||
}
|
||||
}
|
||||
|
||||
// The next highest priority is for non-global where-bounds. However, while we don't
|
||||
// prefer global where-clauses here, we do bail with ambiguity when encountering both
|
||||
// a global and a non-global where-clause.
|
||||
|
|
@ -1907,12 +1942,16 @@ impl<'tcx> SelectionContext<'_, 'tcx> {
|
|||
// fairly arbitrary but once again necessary for backwards compatibility.
|
||||
// If there are multiple applicable candidates which don't affect type inference,
|
||||
// choose the one with the lowest index.
|
||||
let alias_bound = candidates
|
||||
.iter()
|
||||
.filter_map(|c| if let ProjectionCandidate(i) = c.candidate { Some(i) } else { None })
|
||||
.try_reduce(|c1, c2| if has_non_region_infer { None } else { Some(c1.min(c2)) });
|
||||
match alias_bound {
|
||||
Some(Some(index)) => return Some(ProjectionCandidate(index)),
|
||||
match alias_bounds.try_reduce(|(c1, k1), (c2, k2)| {
|
||||
if has_non_region_infer {
|
||||
None
|
||||
} else if c1 < c2 {
|
||||
Some((c1, k1))
|
||||
} else {
|
||||
Some((c2, k2))
|
||||
}
|
||||
}) {
|
||||
Some(Some((idx, kind))) => return Some(ProjectionCandidate { idx, kind }),
|
||||
Some(None) => {}
|
||||
None => return None,
|
||||
}
|
||||
|
|
@ -2001,7 +2040,7 @@ impl<'tcx> SelectionContext<'_, 'tcx> {
|
|||
// Non-global param candidates have already been handled, global
|
||||
// where-bounds get ignored.
|
||||
ParamCandidate(_) | ImplCandidate(_) => true,
|
||||
ProjectionCandidate(_) | ObjectCandidate(_) => unreachable!(),
|
||||
ProjectionCandidate { .. } | ObjectCandidate(_) => unreachable!(),
|
||||
}) {
|
||||
return Some(ImplCandidate(def_id));
|
||||
} else {
|
||||
|
|
|
|||
|
|
@ -383,13 +383,6 @@ pub fn sizedness_fast_path<'tcx>(
|
|||
_ => return false,
|
||||
};
|
||||
|
||||
// FIXME(sized_hierarchy): this temporarily reverts the `sized_hierarchy` feature
|
||||
// while a proper fix for `tests/ui/sized-hierarchy/incomplete-inference-issue-143992.rs`
|
||||
// is pending a proper fix
|
||||
if !tcx.features().sized_hierarchy() && matches!(sizedness, SizedTraitKind::MetaSized) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if trait_pred.self_ty().has_trivial_sizedness(tcx, sizedness) {
|
||||
debug!("fast path -- trivial sizedness");
|
||||
return true;
|
||||
|
|
|
|||
|
|
@ -333,6 +333,8 @@ pub trait Interner:
|
|||
|
||||
fn is_default_trait(self, def_id: Self::TraitId) -> bool;
|
||||
|
||||
fn is_sizedness_trait(self, def_id: Self::TraitId) -> bool;
|
||||
|
||||
fn as_lang_item(self, def_id: Self::DefId) -> Option<SolverLangItem>;
|
||||
|
||||
fn as_trait_lang_item(self, def_id: Self::TraitId) -> Option<SolverTraitLangItem>;
|
||||
|
|
|
|||
|
|
@ -109,6 +109,30 @@ pub struct QueryInput<I: Interner, P> {
|
|||
|
||||
impl<I: Interner, P: Eq> Eq for QueryInput<I, P> {}
|
||||
|
||||
/// Which trait candidates should be preferred over other candidates? By default, prefer where
|
||||
/// bounds over alias bounds. For marker traits, prefer alias bounds over where bounds.
|
||||
#[derive(Clone, Copy, Debug)]
|
||||
pub enum CandidatePreferenceMode {
|
||||
/// Prefers where bounds over alias bounds
|
||||
Default,
|
||||
/// Prefers alias bounds over where bounds
|
||||
Marker,
|
||||
}
|
||||
|
||||
impl CandidatePreferenceMode {
|
||||
/// Given `trait_def_id`, which candidate preference mode should be used?
|
||||
pub fn compute<I: Interner>(cx: I, trait_id: I::TraitId) -> CandidatePreferenceMode {
|
||||
let is_sizedness_or_auto_or_default_goal = cx.is_sizedness_trait(trait_id)
|
||||
|| cx.trait_is_auto(trait_id)
|
||||
|| cx.is_default_trait(trait_id);
|
||||
if is_sizedness_or_auto_or_default_goal {
|
||||
CandidatePreferenceMode::Marker
|
||||
} else {
|
||||
CandidatePreferenceMode::Default
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Possible ways the given goal can be proven.
|
||||
#[derive_where(Clone, Copy, Hash, PartialEq, Debug; I: Interner)]
|
||||
pub enum CandidateSource<I: Interner> {
|
||||
|
|
@ -165,7 +189,7 @@ pub enum CandidateSource<I: Interner> {
|
|||
/// let _y = x.clone();
|
||||
/// }
|
||||
/// ```
|
||||
AliasBound,
|
||||
AliasBound(AliasBoundKind),
|
||||
/// A candidate that is registered only during coherence to represent some
|
||||
/// yet-unknown impl that could be produced downstream without violating orphan
|
||||
/// rules.
|
||||
|
|
@ -183,6 +207,15 @@ pub enum ParamEnvSource {
|
|||
Global,
|
||||
}
|
||||
|
||||
#[derive(Clone, Copy, Hash, PartialEq, Eq, Debug)]
|
||||
#[derive(TypeVisitable_Generic, TypeFoldable_Generic)]
|
||||
pub enum AliasBoundKind {
|
||||
/// Alias bound from the self type of a projection
|
||||
SelfBounds,
|
||||
// Alias bound having recursed on the self type of a projection
|
||||
NonSelfBounds,
|
||||
}
|
||||
|
||||
#[derive(Clone, Copy, Hash, PartialEq, Eq, Debug)]
|
||||
#[cfg_attr(
|
||||
feature = "nightly",
|
||||
|
|
|
|||
|
|
@ -1057,7 +1057,7 @@ marker_impls! {
|
|||
#[rustc_on_unimplemented(message = "can't drop `{Self}`", append_const_msg)]
|
||||
#[rustc_deny_explicit_impl]
|
||||
#[rustc_do_not_implement_via_object]
|
||||
pub const trait Destruct {}
|
||||
pub const trait Destruct: PointeeSized {}
|
||||
|
||||
/// A marker for tuple types.
|
||||
///
|
||||
|
|
|
|||
|
|
@ -6,7 +6,7 @@
|
|||
#![stable(feature = "rust1", since = "1.0.0")]
|
||||
|
||||
use crate::alloc::Layout;
|
||||
use crate::marker::DiscriminantKind;
|
||||
use crate::marker::{Destruct, DiscriminantKind};
|
||||
use crate::panic::const_assert;
|
||||
use crate::{clone, cmp, fmt, hash, intrinsics, ptr};
|
||||
|
||||
|
|
@ -958,8 +958,13 @@ pub const fn replace<T>(dest: &mut T, src: T) -> T {
|
|||
/// [`RefCell`]: crate::cell::RefCell
|
||||
#[inline]
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
#[rustc_const_unstable(feature = "const_destruct", issue = "133214")]
|
||||
#[rustc_diagnostic_item = "mem_drop"]
|
||||
pub fn drop<T>(_x: T) {}
|
||||
pub const fn drop<T>(_x: T)
|
||||
where
|
||||
T: [const] Destruct,
|
||||
{
|
||||
}
|
||||
|
||||
/// Bitwise-copies a value.
|
||||
///
|
||||
|
|
|
|||
|
|
@ -700,7 +700,6 @@ impl<'rwlock, T: ?Sized> RwLockWriteGuard<'rwlock, T> {
|
|||
///
|
||||
/// ```
|
||||
/// #![feature(nonpoison_rwlock)]
|
||||
/// #![feature(rwlock_downgrade)]
|
||||
///
|
||||
/// use std::sync::nonpoison::{RwLock, RwLockWriteGuard};
|
||||
///
|
||||
|
|
@ -719,7 +718,6 @@ impl<'rwlock, T: ?Sized> RwLockWriteGuard<'rwlock, T> {
|
|||
///
|
||||
/// ```
|
||||
/// #![feature(nonpoison_rwlock)]
|
||||
/// #![feature(rwlock_downgrade)]
|
||||
///
|
||||
/// use std::sync::Arc;
|
||||
/// use std::sync::nonpoison::{RwLock, RwLockWriteGuard};
|
||||
|
|
@ -752,8 +750,7 @@ impl<'rwlock, T: ?Sized> RwLockWriteGuard<'rwlock, T> {
|
|||
/// # let final_check = rw.read();
|
||||
/// # assert_eq!(*final_check, 3);
|
||||
/// ```
|
||||
#[unstable(feature = "rwlock_downgrade", issue = "128203")]
|
||||
// #[unstable(feature = "nonpoison_rwlock", issue = "134645")]
|
||||
#[unstable(feature = "nonpoison_rwlock", issue = "134645")]
|
||||
pub fn downgrade(s: Self) -> RwLockReadGuard<'rwlock, T> {
|
||||
let lock = s.lock;
|
||||
|
||||
|
|
|
|||
|
|
@ -813,8 +813,6 @@ impl<'rwlock, T: ?Sized> RwLockWriteGuard<'rwlock, T> {
|
|||
/// `downgrade` takes ownership of the `RwLockWriteGuard` and returns a [`RwLockReadGuard`].
|
||||
///
|
||||
/// ```
|
||||
/// #![feature(rwlock_downgrade)]
|
||||
///
|
||||
/// use std::sync::{RwLock, RwLockWriteGuard};
|
||||
///
|
||||
/// let rw = RwLock::new(0);
|
||||
|
|
@ -831,8 +829,6 @@ impl<'rwlock, T: ?Sized> RwLockWriteGuard<'rwlock, T> {
|
|||
/// thread calling `downgrade` and any reads it performs after downgrading.
|
||||
///
|
||||
/// ```
|
||||
/// #![feature(rwlock_downgrade)]
|
||||
///
|
||||
/// use std::sync::{Arc, RwLock, RwLockWriteGuard};
|
||||
///
|
||||
/// let rw = Arc::new(RwLock::new(1));
|
||||
|
|
@ -863,7 +859,7 @@ impl<'rwlock, T: ?Sized> RwLockWriteGuard<'rwlock, T> {
|
|||
/// # let final_check = rw.read().unwrap();
|
||||
/// # assert_eq!(*final_check, 3);
|
||||
/// ```
|
||||
#[unstable(feature = "rwlock_downgrade", issue = "128203")]
|
||||
#[stable(feature = "rwlock_downgrade", since = "CURRENT_RUSTC_VERSION")]
|
||||
pub fn downgrade(s: Self) -> RwLockReadGuard<'rwlock, T> {
|
||||
let lock = s.lock;
|
||||
|
||||
|
|
|
|||
|
|
@ -4,7 +4,6 @@
|
|||
#![feature(once_cell_try)]
|
||||
#![feature(lock_value_accessors)]
|
||||
#![feature(reentrant_lock)]
|
||||
#![feature(rwlock_downgrade)]
|
||||
#![feature(std_internals)]
|
||||
#![feature(sync_nonpoison)]
|
||||
#![feature(nonpoison_condvar)]
|
||||
|
|
|
|||
|
|
@ -2719,7 +2719,7 @@ fn add_without_unwanted_attributes<'hir>(
|
|||
import_parent: Option<DefId>,
|
||||
) {
|
||||
for attr in new_attrs {
|
||||
if attr.is_doc_comment() {
|
||||
if attr.is_doc_comment().is_some() {
|
||||
attrs.push((Cow::Borrowed(attr), import_parent));
|
||||
continue;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -65,7 +65,7 @@ fn filter_non_cfg_tokens_from_list(args_tokens: &TokenStream) -> Vec<TokenTree>
|
|||
/// it and put them into `attrs`.
|
||||
fn add_only_cfg_attributes(attrs: &mut Vec<Attribute>, new_attrs: &[Attribute]) {
|
||||
for attr in new_attrs {
|
||||
if attr.is_doc_comment() {
|
||||
if attr.is_doc_comment().is_some() {
|
||||
continue;
|
||||
}
|
||||
let mut attr = attr.clone();
|
||||
|
|
|
|||
|
|
@ -1 +1 @@
|
|||
Subproject commit 81c3f77a467359c8be6bc747dc93ec66a6e4ce11
|
||||
Subproject commit 367fd9f213750cd40317803dd0a5a3ce3f0c676d
|
||||
|
|
@ -47,7 +47,7 @@ impl<'tcx> LateLintPass<'tcx> for FourForwardSlashes {
|
|||
.tcx
|
||||
.hir_attrs(item.hir_id())
|
||||
.iter()
|
||||
.filter(|i| i.is_doc_comment())
|
||||
.filter(|i| i.is_doc_comment().is_some())
|
||||
.fold(item.span.shrink_to_lo(), |span, attr| span.to(attr.span()));
|
||||
let (Some(file), _, _, end_line, _) = sm.span_to_location_info(span) else {
|
||||
return;
|
||||
|
|
|
|||
|
|
@ -475,7 +475,7 @@ fn block_has_safety_comment(cx: &LateContext<'_>, span: Span) -> bool {
|
|||
|
||||
fn include_attrs_in_span(cx: &LateContext<'_>, hir_id: HirId, span: Span) -> Span {
|
||||
span.to(cx.tcx.hir_attrs(hir_id).iter().fold(span, |acc, attr| {
|
||||
if attr.is_doc_comment() {
|
||||
if attr.is_doc_comment().is_some() {
|
||||
return acc;
|
||||
}
|
||||
acc.to(attr.span())
|
||||
|
|
|
|||
|
|
@ -1 +1 @@
|
|||
28d0a4a205f9e511ad2f51ee79a4aa19a704a455
|
||||
402ce0ef07d5db9ba26ae5c37ce6aff0c9002052
|
||||
|
|
|
|||
|
|
@ -523,16 +523,16 @@ where
|
|||
}
|
||||
},
|
||||
TraceStyle::Async => Some(
|
||||
span.scope()
|
||||
.from_root()
|
||||
.take(1)
|
||||
.next()
|
||||
.unwrap_or(span)
|
||||
.id()
|
||||
.into_u64()
|
||||
span.scope()
|
||||
.from_root()
|
||||
.take(1)
|
||||
.next()
|
||||
.unwrap_or(span)
|
||||
.id()
|
||||
.into_u64()
|
||||
.cast_signed() // the comment above explains the cast
|
||||
),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn enter_span(&self, span: SpanRef<S>, ts: f64, tid: usize, out: &Sender<Message>) {
|
||||
|
|
@ -567,11 +567,11 @@ where
|
|||
Some(thread_data) => (thread_data, false),
|
||||
None => {
|
||||
let tid = self.max_tid.fetch_add(1, Ordering::SeqCst);
|
||||
let out = self.out.lock().unwrap().clone();
|
||||
let out = self.out.lock().unwrap().clone();
|
||||
let start = TracingChromeInstant::setup_for_thread_and_start(tid);
|
||||
*thread_data = Some(ThreadData { tid, out, start });
|
||||
(thread_data.as_mut().unwrap(), true)
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
start.with_elapsed_micros_subtracting_tracing(|ts| {
|
||||
|
|
@ -583,7 +583,7 @@ where
|
|||
let _ignored = out.send(Message::NewThread(*tid, name));
|
||||
}
|
||||
f(ts, *tid, out);
|
||||
});
|
||||
});
|
||||
});
|
||||
}
|
||||
}
|
||||
|
|
@ -605,15 +605,15 @@ where
|
|||
fn on_record(&self, id: &span::Id, values: &span::Record<'_>, ctx: Context<'_, S>) {
|
||||
if self.include_args {
|
||||
self.with_elapsed_micros_subtracting_tracing(|_, _, _| {
|
||||
let span = ctx.span(id).unwrap();
|
||||
let mut exts = span.extensions_mut();
|
||||
let span = ctx.span(id).unwrap();
|
||||
let mut exts = span.extensions_mut();
|
||||
|
||||
let args = exts.get_mut::<ArgsWrapper>();
|
||||
let args = exts.get_mut::<ArgsWrapper>();
|
||||
|
||||
if let Some(args) = args {
|
||||
let args = Arc::make_mut(&mut args.args);
|
||||
values.record(&mut JsonVisitor { object: args });
|
||||
}
|
||||
if let Some(args) = args {
|
||||
let args = Arc::make_mut(&mut args.args);
|
||||
values.record(&mut JsonVisitor { object: args });
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
|
@ -636,16 +636,16 @@ where
|
|||
|
||||
fn on_new_span(&self, attrs: &span::Attributes<'_>, id: &span::Id, ctx: Context<'_, S>) {
|
||||
self.with_elapsed_micros_subtracting_tracing(|ts, tid, out| {
|
||||
if self.include_args {
|
||||
let mut args = Object::new();
|
||||
attrs.record(&mut JsonVisitor { object: &mut args });
|
||||
ctx.span(id).unwrap().extensions_mut().insert(ArgsWrapper {
|
||||
args: Arc::new(args),
|
||||
});
|
||||
}
|
||||
if let TraceStyle::Threaded = self.trace_style {
|
||||
return;
|
||||
}
|
||||
if self.include_args {
|
||||
let mut args = Object::new();
|
||||
attrs.record(&mut JsonVisitor { object: &mut args });
|
||||
ctx.span(id).unwrap().extensions_mut().insert(ArgsWrapper {
|
||||
args: Arc::new(args),
|
||||
});
|
||||
}
|
||||
if let TraceStyle::Threaded = self.trace_style {
|
||||
return;
|
||||
}
|
||||
|
||||
self.enter_span(ctx.span(id).expect("Span not found."), ts, tid, out);
|
||||
});
|
||||
|
|
|
|||
|
|
@ -38,47 +38,47 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
|
|||
for i in 0..dest_len {
|
||||
let op = this.read_immediate(&this.project_index(&op, i)?)?;
|
||||
let dest = this.project_index(&dest, i)?;
|
||||
let ty::Float(float_ty) = op.layout.ty.kind() else {
|
||||
span_bug!(this.cur_span(), "{} operand is not a float", intrinsic_name)
|
||||
};
|
||||
// Using host floats except for sqrt (but it's fine, these operations do not
|
||||
// have guaranteed precision).
|
||||
let ty::Float(float_ty) = op.layout.ty.kind() else {
|
||||
span_bug!(this.cur_span(), "{} operand is not a float", intrinsic_name)
|
||||
};
|
||||
// Using host floats except for sqrt (but it's fine, these operations do not
|
||||
// have guaranteed precision).
|
||||
let val = match float_ty {
|
||||
FloatTy::F16 => unimplemented!("f16_f128"),
|
||||
FloatTy::F32 => {
|
||||
let f = op.to_scalar().to_f32()?;
|
||||
FloatTy::F16 => unimplemented!("f16_f128"),
|
||||
FloatTy::F32 => {
|
||||
let f = op.to_scalar().to_f32()?;
|
||||
let res = match intrinsic_name {
|
||||
"fsqrt" => math::sqrt(f),
|
||||
"fsin" => f.to_host().sin().to_soft(),
|
||||
"fcos" => f.to_host().cos().to_soft(),
|
||||
"fexp" => f.to_host().exp().to_soft(),
|
||||
"fexp2" => f.to_host().exp2().to_soft(),
|
||||
"flog" => f.to_host().ln().to_soft(),
|
||||
"flog2" => f.to_host().log2().to_soft(),
|
||||
"flog10" => f.to_host().log10().to_soft(),
|
||||
_ => bug!(),
|
||||
};
|
||||
let res = this.adjust_nan(res, &[f]);
|
||||
Scalar::from(res)
|
||||
}
|
||||
FloatTy::F64 => {
|
||||
let f = op.to_scalar().to_f64()?;
|
||||
let res = match intrinsic_name {
|
||||
"fsqrt" => math::sqrt(f),
|
||||
"fsin" => f.to_host().sin().to_soft(),
|
||||
"fcos" => f.to_host().cos().to_soft(),
|
||||
"fexp" => f.to_host().exp().to_soft(),
|
||||
"fexp2" => f.to_host().exp2().to_soft(),
|
||||
"flog" => f.to_host().ln().to_soft(),
|
||||
"flog2" => f.to_host().log2().to_soft(),
|
||||
"flog10" => f.to_host().log10().to_soft(),
|
||||
_ => bug!(),
|
||||
};
|
||||
let res = this.adjust_nan(res, &[f]);
|
||||
Scalar::from(res)
|
||||
}
|
||||
FloatTy::F128 => unimplemented!("f16_f128"),
|
||||
"fsqrt" => math::sqrt(f),
|
||||
"fsin" => f.to_host().sin().to_soft(),
|
||||
"fcos" => f.to_host().cos().to_soft(),
|
||||
"fexp" => f.to_host().exp().to_soft(),
|
||||
"fexp2" => f.to_host().exp2().to_soft(),
|
||||
"flog" => f.to_host().ln().to_soft(),
|
||||
"flog2" => f.to_host().log2().to_soft(),
|
||||
"flog10" => f.to_host().log10().to_soft(),
|
||||
_ => bug!(),
|
||||
};
|
||||
let res = this.adjust_nan(res, &[f]);
|
||||
Scalar::from(res)
|
||||
}
|
||||
FloatTy::F64 => {
|
||||
let f = op.to_scalar().to_f64()?;
|
||||
let res = match intrinsic_name {
|
||||
"fsqrt" => math::sqrt(f),
|
||||
"fsin" => f.to_host().sin().to_soft(),
|
||||
"fcos" => f.to_host().cos().to_soft(),
|
||||
"fexp" => f.to_host().exp().to_soft(),
|
||||
"fexp2" => f.to_host().exp2().to_soft(),
|
||||
"flog" => f.to_host().ln().to_soft(),
|
||||
"flog2" => f.to_host().log2().to_soft(),
|
||||
"flog10" => f.to_host().log10().to_soft(),
|
||||
_ => bug!(),
|
||||
};
|
||||
let res = this.adjust_nan(res, &[f]);
|
||||
Scalar::from(res)
|
||||
}
|
||||
FloatTy::F128 => unimplemented!("f16_f128"),
|
||||
};
|
||||
|
||||
this.write_scalar(val, &dest)?;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -53,6 +53,7 @@
|
|||
extern crate rustc_abi;
|
||||
extern crate rustc_apfloat;
|
||||
extern crate rustc_ast;
|
||||
extern crate rustc_codegen_ssa;
|
||||
extern crate rustc_const_eval;
|
||||
extern crate rustc_data_structures;
|
||||
extern crate rustc_errors;
|
||||
|
|
|
|||
|
|
@ -12,6 +12,8 @@ use rand::rngs::StdRng;
|
|||
use rand::{Rng, SeedableRng};
|
||||
use rustc_abi::{Align, ExternAbi, Size};
|
||||
use rustc_apfloat::{Float, FloatConvert};
|
||||
use rustc_ast::expand::allocator::{self, SpecialAllocatorMethod};
|
||||
use rustc_data_structures::either::Either;
|
||||
use rustc_data_structures::fx::{FxHashMap, FxHashSet};
|
||||
#[allow(unused)]
|
||||
use rustc_data_structures::static_assert_size;
|
||||
|
|
@ -27,6 +29,7 @@ use rustc_middle::ty::{self, Instance, Ty, TyCtxt};
|
|||
use rustc_session::config::InliningThreshold;
|
||||
use rustc_span::def_id::{CrateNum, DefId};
|
||||
use rustc_span::{Span, SpanData, Symbol};
|
||||
use rustc_symbol_mangling::mangle_internal_symbol;
|
||||
use rustc_target::callconv::FnAbi;
|
||||
|
||||
use crate::alloc_addresses::EvalContextExt;
|
||||
|
|
@ -652,6 +655,10 @@ pub struct MiriMachine<'tcx> {
|
|||
pub(crate) pthread_rwlock_sanity: Cell<bool>,
|
||||
pub(crate) pthread_condvar_sanity: Cell<bool>,
|
||||
|
||||
/// (Foreign) symbols that are synthesized as part of the allocator shim: the key indicates the
|
||||
/// name of the symbol being synthesized; the value indicates whether this should invoke some
|
||||
/// other symbol or whether this has special allocator semantics.
|
||||
pub(crate) allocator_shim_symbols: FxHashMap<Symbol, Either<Symbol, SpecialAllocatorMethod>>,
|
||||
/// Cache for `mangle_internal_symbol`.
|
||||
pub(crate) mangle_internal_symbol_cache: FxHashMap<&'static str, String>,
|
||||
|
||||
|
|
@ -819,6 +826,7 @@ impl<'tcx> MiriMachine<'tcx> {
|
|||
pthread_mutex_sanity: Cell::new(false),
|
||||
pthread_rwlock_sanity: Cell::new(false),
|
||||
pthread_condvar_sanity: Cell::new(false),
|
||||
allocator_shim_symbols: Self::allocator_shim_symbols(tcx),
|
||||
mangle_internal_symbol_cache: Default::default(),
|
||||
force_intrinsic_fallback: config.force_intrinsic_fallback,
|
||||
float_nondet: config.float_nondet,
|
||||
|
|
@ -827,6 +835,36 @@ impl<'tcx> MiriMachine<'tcx> {
|
|||
}
|
||||
}
|
||||
|
||||
fn allocator_shim_symbols(
|
||||
tcx: TyCtxt<'tcx>,
|
||||
) -> FxHashMap<Symbol, Either<Symbol, SpecialAllocatorMethod>> {
|
||||
use rustc_codegen_ssa::base::allocator_shim_contents;
|
||||
|
||||
// codegen uses `allocator_kind_for_codegen` here, but that's only needed to deal with
|
||||
// dylibs which we do not support.
|
||||
let Some(kind) = tcx.allocator_kind(()) else {
|
||||
return Default::default();
|
||||
};
|
||||
let methods = allocator_shim_contents(tcx, kind);
|
||||
let mut symbols = FxHashMap::default();
|
||||
for method in methods {
|
||||
let from_name = Symbol::intern(&mangle_internal_symbol(
|
||||
tcx,
|
||||
&allocator::global_fn_name(method.name),
|
||||
));
|
||||
let to = match method.special {
|
||||
Some(special) => Either::Right(special),
|
||||
None =>
|
||||
Either::Left(Symbol::intern(&mangle_internal_symbol(
|
||||
tcx,
|
||||
&allocator::default_fn_name(method.name),
|
||||
))),
|
||||
};
|
||||
symbols.try_insert(from_name, to).unwrap();
|
||||
}
|
||||
symbols
|
||||
}
|
||||
|
||||
pub(crate) fn late_init(
|
||||
ecx: &mut MiriInterpCx<'tcx>,
|
||||
config: &MiriConfig,
|
||||
|
|
@ -992,6 +1030,7 @@ impl VisitProvenance for MiriMachine<'_> {
|
|||
pthread_mutex_sanity: _,
|
||||
pthread_rwlock_sanity: _,
|
||||
pthread_condvar_sanity: _,
|
||||
allocator_shim_symbols: _,
|
||||
mangle_internal_symbol_cache: _,
|
||||
force_intrinsic_fallback: _,
|
||||
float_nondet: _,
|
||||
|
|
|
|||
|
|
@ -1,5 +1,8 @@
|
|||
use rustc_abi::{Align, Size};
|
||||
use rustc_ast::expand::allocator::AllocatorKind;
|
||||
use rustc_abi::{Align, AlignFromBytesError, CanonAbi, Size};
|
||||
use rustc_ast::expand::allocator::SpecialAllocatorMethod;
|
||||
use rustc_middle::ty::Ty;
|
||||
use rustc_span::Symbol;
|
||||
use rustc_target::callconv::FnAbi;
|
||||
|
||||
use crate::*;
|
||||
|
||||
|
|
@ -54,30 +57,100 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
|
|||
Align::from_bytes(prev_power_of_two(size)).unwrap()
|
||||
}
|
||||
|
||||
/// Emulates calling the internal __rust_* allocator functions
|
||||
fn emulate_allocator(
|
||||
/// Check some basic requirements for this allocation request:
|
||||
/// non-zero size, power-of-two alignment.
|
||||
fn check_rust_alloc_request(&self, size: u64, align: u64) -> InterpResult<'tcx> {
|
||||
let this = self.eval_context_ref();
|
||||
if size == 0 {
|
||||
throw_ub_format!("creating allocation with size 0");
|
||||
}
|
||||
if size > this.max_size_of_val().bytes() {
|
||||
throw_ub_format!("creating an allocation larger than half the address space");
|
||||
}
|
||||
if let Err(e) = Align::from_bytes(align) {
|
||||
match e {
|
||||
AlignFromBytesError::TooLarge(_) => {
|
||||
throw_unsup_format!(
|
||||
"creating allocation with alignment {align} exceeding rustc's maximum \
|
||||
supported value"
|
||||
);
|
||||
}
|
||||
AlignFromBytesError::NotPowerOfTwo(_) => {
|
||||
throw_ub_format!("creating allocation with non-power-of-two alignment {align}");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
interp_ok(())
|
||||
}
|
||||
|
||||
fn rust_special_allocator_method(
|
||||
&mut self,
|
||||
default: impl FnOnce(&mut MiriInterpCx<'tcx>) -> InterpResult<'tcx>,
|
||||
) -> InterpResult<'tcx, EmulateItemResult> {
|
||||
method: SpecialAllocatorMethod,
|
||||
link_name: Symbol,
|
||||
abi: &FnAbi<'tcx, Ty<'tcx>>,
|
||||
args: &[OpTy<'tcx>],
|
||||
dest: &PlaceTy<'tcx>,
|
||||
) -> InterpResult<'tcx> {
|
||||
let this = self.eval_context_mut();
|
||||
|
||||
let Some(allocator_kind) = this.tcx.allocator_kind(()) else {
|
||||
// in real code, this symbol does not exist without an allocator
|
||||
return interp_ok(EmulateItemResult::NotSupported);
|
||||
};
|
||||
match method {
|
||||
SpecialAllocatorMethod::Alloc | SpecialAllocatorMethod::AllocZeroed => {
|
||||
let [size, align] =
|
||||
this.check_shim_sig_lenient(abi, CanonAbi::Rust, link_name, args)?;
|
||||
let size = this.read_target_usize(size)?;
|
||||
let align = this.read_target_usize(align)?;
|
||||
|
||||
match allocator_kind {
|
||||
AllocatorKind::Global => {
|
||||
// When `#[global_allocator]` is used, `__rust_*` is defined by the macro expansion
|
||||
// of this attribute. As such we have to call an exported Rust function,
|
||||
// and not execute any Miri shim. Somewhat unintuitively doing so is done
|
||||
// by returning `NotSupported`, which triggers the `lookup_exported_symbol`
|
||||
// fallback case in `emulate_foreign_item`.
|
||||
interp_ok(EmulateItemResult::NotSupported)
|
||||
this.check_rust_alloc_request(size, align)?;
|
||||
|
||||
let ptr = this.allocate_ptr(
|
||||
Size::from_bytes(size),
|
||||
Align::from_bytes(align).unwrap(),
|
||||
MiriMemoryKind::Rust.into(),
|
||||
if matches!(method, SpecialAllocatorMethod::AllocZeroed) {
|
||||
AllocInit::Zero
|
||||
} else {
|
||||
AllocInit::Uninit
|
||||
},
|
||||
)?;
|
||||
|
||||
this.write_pointer(ptr, dest)
|
||||
}
|
||||
AllocatorKind::Default => {
|
||||
default(this)?;
|
||||
interp_ok(EmulateItemResult::NeedsReturn)
|
||||
SpecialAllocatorMethod::Dealloc => {
|
||||
let [ptr, old_size, align] =
|
||||
this.check_shim_sig_lenient(abi, CanonAbi::Rust, link_name, args)?;
|
||||
let ptr = this.read_pointer(ptr)?;
|
||||
let old_size = this.read_target_usize(old_size)?;
|
||||
let align = this.read_target_usize(align)?;
|
||||
|
||||
// No need to check old_size/align; we anyway check that they match the allocation.
|
||||
this.deallocate_ptr(
|
||||
ptr,
|
||||
Some((Size::from_bytes(old_size), Align::from_bytes(align).unwrap())),
|
||||
MiriMemoryKind::Rust.into(),
|
||||
)
|
||||
}
|
||||
SpecialAllocatorMethod::Realloc => {
|
||||
let [ptr, old_size, align, new_size] =
|
||||
this.check_shim_sig_lenient(abi, CanonAbi::Rust, link_name, args)?;
|
||||
let ptr = this.read_pointer(ptr)?;
|
||||
let old_size = this.read_target_usize(old_size)?;
|
||||
let align = this.read_target_usize(align)?;
|
||||
let new_size = this.read_target_usize(new_size)?;
|
||||
// No need to check old_size; we anyway check that they match the allocation.
|
||||
|
||||
this.check_rust_alloc_request(new_size, align)?;
|
||||
|
||||
let align = Align::from_bytes(align).unwrap();
|
||||
let new_ptr = this.reallocate_ptr(
|
||||
ptr,
|
||||
Some((Size::from_bytes(old_size), align)),
|
||||
Size::from_bytes(new_size),
|
||||
align,
|
||||
MiriMemoryKind::Rust.into(),
|
||||
AllocInit::Uninit,
|
||||
)?;
|
||||
this.write_pointer(new_ptr, dest)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -2,8 +2,9 @@ use std::collections::hash_map::Entry;
|
|||
use std::io::Write;
|
||||
use std::path::Path;
|
||||
|
||||
use rustc_abi::{Align, AlignFromBytesError, CanonAbi, Size};
|
||||
use rustc_ast::expand::allocator::AllocatorKind;
|
||||
use rustc_abi::{Align, CanonAbi, Size};
|
||||
use rustc_ast::expand::allocator::NO_ALLOC_SHIM_IS_UNSTABLE;
|
||||
use rustc_data_structures::either::Either;
|
||||
use rustc_hir::attrs::Linkage;
|
||||
use rustc_hir::def::DefKind;
|
||||
use rustc_hir::def_id::CrateNum;
|
||||
|
|
@ -11,6 +12,7 @@ use rustc_middle::middle::codegen_fn_attrs::CodegenFnAttrFlags;
|
|||
use rustc_middle::mir::interpret::AllocInit;
|
||||
use rustc_middle::ty::{Instance, Ty};
|
||||
use rustc_middle::{mir, ty};
|
||||
use rustc_session::config::OomStrategy;
|
||||
use rustc_span::Symbol;
|
||||
use rustc_target::callconv::FnAbi;
|
||||
|
||||
|
|
@ -50,31 +52,21 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
|
|||
) -> InterpResult<'tcx, Option<(&'tcx mir::Body<'tcx>, ty::Instance<'tcx>)>> {
|
||||
let this = self.eval_context_mut();
|
||||
|
||||
// Some shims forward to other MIR bodies.
|
||||
match link_name.as_str() {
|
||||
// This allocator function has forwarding shims synthesized during normal codegen
|
||||
// (see `allocator_shim_contents`); this is where we emulate that behavior.
|
||||
// FIXME should use global_fn_name, but mangle_internal_symbol requires a static str.
|
||||
name if name == this.mangle_internal_symbol("__rust_alloc_error_handler") => {
|
||||
// Forward to the right symbol that implements this function.
|
||||
let Some(handler_kind) = this.tcx.alloc_error_handler_kind(()) else {
|
||||
// in real code, this symbol does not exist without an allocator
|
||||
throw_unsup_format!(
|
||||
"`__rust_alloc_error_handler` cannot be called when no alloc error handler is set"
|
||||
);
|
||||
};
|
||||
if handler_kind == AllocatorKind::Default {
|
||||
let name =
|
||||
Symbol::intern(this.mangle_internal_symbol("__rdl_alloc_error_handler"));
|
||||
// Handle allocator shim.
|
||||
if let Some(shim) = this.machine.allocator_shim_symbols.get(&link_name) {
|
||||
match *shim {
|
||||
Either::Left(other_fn) => {
|
||||
let handler = this
|
||||
.lookup_exported_symbol(name)?
|
||||
.lookup_exported_symbol(other_fn)?
|
||||
.expect("missing alloc error handler symbol");
|
||||
return interp_ok(Some(handler));
|
||||
}
|
||||
// Fall through to the `lookup_exported_symbol` below which should find
|
||||
// a `__rust_alloc_error_handler`.
|
||||
Either::Right(special) => {
|
||||
this.rust_special_allocator_method(special, link_name, abi, args, dest)?;
|
||||
this.return_to_block(ret)?;
|
||||
return interp_ok(None);
|
||||
}
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
|
||||
// FIXME: avoid allocating memory
|
||||
|
|
@ -254,33 +246,6 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
|
|||
|
||||
impl<'tcx> EvalContextExtPriv<'tcx> for crate::MiriInterpCx<'tcx> {}
|
||||
trait EvalContextExtPriv<'tcx>: crate::MiriInterpCxExt<'tcx> {
|
||||
/// Check some basic requirements for this allocation request:
|
||||
/// non-zero size, power-of-two alignment.
|
||||
fn check_rustc_alloc_request(&self, size: u64, align: u64) -> InterpResult<'tcx> {
|
||||
let this = self.eval_context_ref();
|
||||
if size == 0 {
|
||||
throw_ub_format!("creating allocation with size 0");
|
||||
}
|
||||
if size > this.max_size_of_val().bytes() {
|
||||
throw_ub_format!("creating an allocation larger than half the address space");
|
||||
}
|
||||
if let Err(e) = Align::from_bytes(align) {
|
||||
match e {
|
||||
AlignFromBytesError::TooLarge(_) => {
|
||||
throw_unsup_format!(
|
||||
"creating allocation with alignment {align} exceeding rustc's maximum \
|
||||
supported value"
|
||||
);
|
||||
}
|
||||
AlignFromBytesError::NotPowerOfTwo(_) => {
|
||||
throw_ub_format!("creating allocation with non-power-of-two alignment {align}");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
interp_ok(())
|
||||
}
|
||||
|
||||
fn emulate_foreign_item_inner(
|
||||
&mut self,
|
||||
link_name: Symbol,
|
||||
|
|
@ -340,7 +305,51 @@ trait EvalContextExtPriv<'tcx>: crate::MiriInterpCxExt<'tcx> {
|
|||
// Here we dispatch all the shims for foreign functions. If you have a platform specific
|
||||
// shim, add it to the corresponding submodule.
|
||||
match link_name.as_str() {
|
||||
// Magic functions Rust emits (and not as part of the allocator shim).
|
||||
name if name == this.mangle_internal_symbol(NO_ALLOC_SHIM_IS_UNSTABLE) => {
|
||||
// This is a no-op shim that only exists to prevent making the allocator shims
|
||||
// instantly stable.
|
||||
let [] = this.check_shim_sig_lenient(abi, CanonAbi::Rust, link_name, args)?;
|
||||
}
|
||||
name if name == this.mangle_internal_symbol(OomStrategy::SYMBOL) => {
|
||||
// Gets the value of the `oom` option.
|
||||
let [] = this.check_shim_sig_lenient(abi, CanonAbi::Rust, link_name, args)?;
|
||||
let val = this.tcx.sess.opts.unstable_opts.oom.should_panic();
|
||||
this.write_int(val, dest)?;
|
||||
}
|
||||
|
||||
// Miri-specific extern functions
|
||||
"miri_alloc" => {
|
||||
let [size, align] =
|
||||
this.check_shim_sig_lenient(abi, CanonAbi::Rust, link_name, args)?;
|
||||
let size = this.read_target_usize(size)?;
|
||||
let align = this.read_target_usize(align)?;
|
||||
|
||||
this.check_rust_alloc_request(size, align)?;
|
||||
|
||||
let ptr = this.allocate_ptr(
|
||||
Size::from_bytes(size),
|
||||
Align::from_bytes(align).unwrap(),
|
||||
MiriMemoryKind::Miri.into(),
|
||||
AllocInit::Uninit,
|
||||
)?;
|
||||
|
||||
this.write_pointer(ptr, dest)?;
|
||||
}
|
||||
"miri_dealloc" => {
|
||||
let [ptr, old_size, align] =
|
||||
this.check_shim_sig_lenient(abi, CanonAbi::Rust, link_name, args)?;
|
||||
let ptr = this.read_pointer(ptr)?;
|
||||
let old_size = this.read_target_usize(old_size)?;
|
||||
let align = this.read_target_usize(align)?;
|
||||
|
||||
// No need to check old_size/align; we anyway check that they match the allocation.
|
||||
this.deallocate_ptr(
|
||||
ptr,
|
||||
Some((Size::from_bytes(old_size), Align::from_bytes(align).unwrap())),
|
||||
MiriMemoryKind::Miri.into(),
|
||||
)?;
|
||||
}
|
||||
"miri_start_unwind" => {
|
||||
let [payload] =
|
||||
this.check_shim_sig_lenient(abi, CanonAbi::Rust, link_name, args)?;
|
||||
|
|
@ -492,7 +501,6 @@ trait EvalContextExtPriv<'tcx>: crate::MiriInterpCxExt<'tcx> {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
// GenMC mode: Assume statements block the current thread when their condition is false.
|
||||
"miri_genmc_assume" => {
|
||||
let [condition] =
|
||||
|
|
@ -579,133 +587,6 @@ trait EvalContextExtPriv<'tcx>: crate::MiriInterpCxExt<'tcx> {
|
|||
}
|
||||
}
|
||||
|
||||
// Rust allocation
|
||||
name if name == this.mangle_internal_symbol("__rust_alloc") || name == "miri_alloc" => {
|
||||
let default = |ecx: &mut MiriInterpCx<'tcx>| {
|
||||
// Only call `check_shim` when `#[global_allocator]` isn't used. When that
|
||||
// macro is used, we act like no shim exists, so that the exported function can run.
|
||||
let [size, align] =
|
||||
ecx.check_shim_sig_lenient(abi, CanonAbi::Rust, link_name, args)?;
|
||||
let size = ecx.read_target_usize(size)?;
|
||||
let align = ecx.read_target_usize(align)?;
|
||||
|
||||
ecx.check_rustc_alloc_request(size, align)?;
|
||||
|
||||
let memory_kind = match link_name.as_str() {
|
||||
"miri_alloc" => MiriMemoryKind::Miri,
|
||||
_ => MiriMemoryKind::Rust,
|
||||
};
|
||||
|
||||
let ptr = ecx.allocate_ptr(
|
||||
Size::from_bytes(size),
|
||||
Align::from_bytes(align).unwrap(),
|
||||
memory_kind.into(),
|
||||
AllocInit::Uninit,
|
||||
)?;
|
||||
|
||||
ecx.write_pointer(ptr, dest)
|
||||
};
|
||||
|
||||
match link_name.as_str() {
|
||||
"miri_alloc" => {
|
||||
default(this)?;
|
||||
return interp_ok(EmulateItemResult::NeedsReturn);
|
||||
}
|
||||
_ => return this.emulate_allocator(default),
|
||||
}
|
||||
}
|
||||
name if name == this.mangle_internal_symbol("__rust_alloc_zeroed") => {
|
||||
return this.emulate_allocator(|this| {
|
||||
// See the comment for `__rust_alloc` why `check_shim` is only called in the
|
||||
// default case.
|
||||
let [size, align] =
|
||||
this.check_shim_sig_lenient(abi, CanonAbi::Rust, link_name, args)?;
|
||||
let size = this.read_target_usize(size)?;
|
||||
let align = this.read_target_usize(align)?;
|
||||
|
||||
this.check_rustc_alloc_request(size, align)?;
|
||||
|
||||
let ptr = this.allocate_ptr(
|
||||
Size::from_bytes(size),
|
||||
Align::from_bytes(align).unwrap(),
|
||||
MiriMemoryKind::Rust.into(),
|
||||
AllocInit::Zero,
|
||||
)?;
|
||||
this.write_pointer(ptr, dest)
|
||||
});
|
||||
}
|
||||
name if name == this.mangle_internal_symbol("__rust_dealloc")
|
||||
|| name == "miri_dealloc" =>
|
||||
{
|
||||
let default = |ecx: &mut MiriInterpCx<'tcx>| {
|
||||
// See the comment for `__rust_alloc` why `check_shim` is only called in the
|
||||
// default case.
|
||||
let [ptr, old_size, align] =
|
||||
ecx.check_shim_sig_lenient(abi, CanonAbi::Rust, link_name, args)?;
|
||||
let ptr = ecx.read_pointer(ptr)?;
|
||||
let old_size = ecx.read_target_usize(old_size)?;
|
||||
let align = ecx.read_target_usize(align)?;
|
||||
|
||||
let memory_kind = match link_name.as_str() {
|
||||
"miri_dealloc" => MiriMemoryKind::Miri,
|
||||
_ => MiriMemoryKind::Rust,
|
||||
};
|
||||
|
||||
// No need to check old_size/align; we anyway check that they match the allocation.
|
||||
ecx.deallocate_ptr(
|
||||
ptr,
|
||||
Some((Size::from_bytes(old_size), Align::from_bytes(align).unwrap())),
|
||||
memory_kind.into(),
|
||||
)
|
||||
};
|
||||
|
||||
match link_name.as_str() {
|
||||
"miri_dealloc" => {
|
||||
default(this)?;
|
||||
return interp_ok(EmulateItemResult::NeedsReturn);
|
||||
}
|
||||
_ => return this.emulate_allocator(default),
|
||||
}
|
||||
}
|
||||
name if name == this.mangle_internal_symbol("__rust_realloc") => {
|
||||
return this.emulate_allocator(|this| {
|
||||
// See the comment for `__rust_alloc` why `check_shim` is only called in the
|
||||
// default case.
|
||||
let [ptr, old_size, align, new_size] =
|
||||
this.check_shim_sig_lenient(abi, CanonAbi::Rust, link_name, args)?;
|
||||
let ptr = this.read_pointer(ptr)?;
|
||||
let old_size = this.read_target_usize(old_size)?;
|
||||
let align = this.read_target_usize(align)?;
|
||||
let new_size = this.read_target_usize(new_size)?;
|
||||
// No need to check old_size; we anyway check that they match the allocation.
|
||||
|
||||
this.check_rustc_alloc_request(new_size, align)?;
|
||||
|
||||
let align = Align::from_bytes(align).unwrap();
|
||||
let new_ptr = this.reallocate_ptr(
|
||||
ptr,
|
||||
Some((Size::from_bytes(old_size), align)),
|
||||
Size::from_bytes(new_size),
|
||||
align,
|
||||
MiriMemoryKind::Rust.into(),
|
||||
AllocInit::Uninit,
|
||||
)?;
|
||||
this.write_pointer(new_ptr, dest)
|
||||
});
|
||||
}
|
||||
name if name == this.mangle_internal_symbol("__rust_no_alloc_shim_is_unstable_v2") => {
|
||||
// This is a no-op shim that only exists to prevent making the allocator shims instantly stable.
|
||||
let [] = this.check_shim_sig_lenient(abi, CanonAbi::Rust, link_name, args)?;
|
||||
}
|
||||
name if name
|
||||
== this.mangle_internal_symbol("__rust_alloc_error_handler_should_panic_v2") =>
|
||||
{
|
||||
// Gets the value of the `oom` option.
|
||||
let [] = this.check_shim_sig_lenient(abi, CanonAbi::Rust, link_name, args)?;
|
||||
let val = this.tcx.sess.opts.unstable_opts.oom.should_panic();
|
||||
this.write_int(val, dest)?;
|
||||
}
|
||||
|
||||
// C memory handling functions
|
||||
"memcmp" => {
|
||||
let [left, right, n] =
|
||||
|
|
|
|||
|
|
@ -1,33 +0,0 @@
|
|||
error: implementation of `FnOnce` is not general enough
|
||||
--> $DIR/higher-ranked-auto-trait-14.rs:20:5
|
||||
|
|
||||
LL | / async move {
|
||||
LL | | let xs = unique_x.union(&cached)
|
||||
LL | | // .copied() // works
|
||||
LL | | .map(|x| *x) // error
|
||||
LL | | ;
|
||||
LL | | let blah = val.blah(xs.into_iter()).await;
|
||||
LL | | }
|
||||
| |_____^ implementation of `FnOnce` is not general enough
|
||||
|
|
||||
= note: closure with signature `fn(&'0 u32) -> u32` must implement `FnOnce<(&'1 u32,)>`, for any two lifetimes `'0` and `'1`...
|
||||
= note: ...but it actually implements `FnOnce<(&u32,)>`
|
||||
|
||||
error: implementation of `FnOnce` is not general enough
|
||||
--> $DIR/higher-ranked-auto-trait-14.rs:20:5
|
||||
|
|
||||
LL | / async move {
|
||||
LL | | let xs = unique_x.union(&cached)
|
||||
LL | | // .copied() // works
|
||||
LL | | .map(|x| *x) // error
|
||||
LL | | ;
|
||||
LL | | let blah = val.blah(xs.into_iter()).await;
|
||||
LL | | }
|
||||
| |_____^ implementation of `FnOnce` is not general enough
|
||||
|
|
||||
= note: closure with signature `fn(&'0 u32) -> u32` must implement `FnOnce<(&'1 u32,)>`, for any two lifetimes `'0` and `'1`...
|
||||
= note: ...but it actually implements `FnOnce<(&u32,)>`
|
||||
= note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
|
||||
|
||||
error: aborting due to 2 previous errors
|
||||
|
||||
|
|
@ -1,9 +1,8 @@
|
|||
// Repro for <https://github.com/rust-lang/rust/issues/124757#issue-2279603232>.
|
||||
//@ check-pass
|
||||
//@ edition: 2021
|
||||
//@ revisions: assumptions no_assumptions
|
||||
//@[assumptions] compile-flags: -Zhigher-ranked-assumptions
|
||||
//@[assumptions] check-pass
|
||||
//@[no_assumptions] known-bug: #110338
|
||||
|
||||
use std::collections::HashSet;
|
||||
use std::future::Future;
|
||||
|
|
|
|||
|
|
@ -1,49 +0,0 @@
|
|||
error: lifetime bound not satisfied
|
||||
--> $DIR/higher-ranked-auto-trait-2.rs:16:9
|
||||
|
|
||||
LL | / async move {
|
||||
LL | | // asks for an unspecified lifetime to outlive itself? weird diagnostics
|
||||
LL | | self.run(t).await;
|
||||
LL | | }
|
||||
| |_________^
|
||||
|
|
||||
= note: this is a known limitation that will be removed in the future (see issue #100013 <https://github.com/rust-lang/rust/issues/100013> for more information)
|
||||
|
||||
error: lifetime bound not satisfied
|
||||
--> $DIR/higher-ranked-auto-trait-2.rs:16:9
|
||||
|
|
||||
LL | / async move {
|
||||
LL | | // asks for an unspecified lifetime to outlive itself? weird diagnostics
|
||||
LL | | self.run(t).await;
|
||||
LL | | }
|
||||
| |_________^
|
||||
|
|
||||
= note: this is a known limitation that will be removed in the future (see issue #100013 <https://github.com/rust-lang/rust/issues/100013> for more information)
|
||||
= note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
|
||||
|
||||
error: lifetime bound not satisfied
|
||||
--> $DIR/higher-ranked-auto-trait-2.rs:16:9
|
||||
|
|
||||
LL | / async move {
|
||||
LL | | // asks for an unspecified lifetime to outlive itself? weird diagnostics
|
||||
LL | | self.run(t).await;
|
||||
LL | | }
|
||||
| |_________^
|
||||
|
|
||||
= note: this is a known limitation that will be removed in the future (see issue #100013 <https://github.com/rust-lang/rust/issues/100013> for more information)
|
||||
= note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
|
||||
|
||||
error: lifetime bound not satisfied
|
||||
--> $DIR/higher-ranked-auto-trait-2.rs:16:9
|
||||
|
|
||||
LL | / async move {
|
||||
LL | | // asks for an unspecified lifetime to outlive itself? weird diagnostics
|
||||
LL | | self.run(t).await;
|
||||
LL | | }
|
||||
| |_________^
|
||||
|
|
||||
= note: this is a known limitation that will be removed in the future (see issue #100013 <https://github.com/rust-lang/rust/issues/100013> for more information)
|
||||
= note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
|
||||
|
||||
error: aborting due to 4 previous errors
|
||||
|
||||
|
|
@ -1,9 +1,8 @@
|
|||
// Repro for <https://github.com/rust-lang/rust/issues/111105#issue-1692860759>.
|
||||
//@ check-pass
|
||||
//@ edition: 2021
|
||||
//@ revisions: assumptions no_assumptions
|
||||
//@[assumptions] compile-flags: -Zhigher-ranked-assumptions
|
||||
//@[assumptions] check-pass
|
||||
//@[no_assumptions] known-bug: #110338
|
||||
|
||||
use std::future::Future;
|
||||
|
||||
|
|
|
|||
|
|
@ -1,12 +0,0 @@
|
|||
error: lifetime bound not satisfied
|
||||
--> $DIR/higher-ranked-auto-trait-3.rs:66:9
|
||||
|
|
||||
LL | / async {
|
||||
LL | | self.fi_2.get_iter(cx).await;
|
||||
LL | | }
|
||||
| |_________^
|
||||
|
|
||||
= note: this is a known limitation that will be removed in the future (see issue #100013 <https://github.com/rust-lang/rust/issues/100013> for more information)
|
||||
|
||||
error: aborting due to 1 previous error
|
||||
|
||||
|
|
@ -1,9 +1,8 @@
|
|||
// Repro for <https://github.com/rust-lang/rust/issues/100013#issue-1323807923>.
|
||||
//@ check-pass
|
||||
//@ edition: 2021
|
||||
//@ revisions: assumptions no_assumptions
|
||||
//@[assumptions] compile-flags: -Zhigher-ranked-assumptions
|
||||
//@[assumptions] check-pass
|
||||
//@[no_assumptions] known-bug: #110338
|
||||
|
||||
#![feature(impl_trait_in_assoc_type)]
|
||||
|
||||
|
|
|
|||
|
|
@ -1,8 +0,0 @@
|
|||
error: `S` does not live long enough
|
||||
--> $DIR/higher-ranked-auto-trait-7.rs:26:5
|
||||
|
|
||||
LL | future::<'a, S, _>(async move {
|
||||
| ^^^^^^^^^^^^^^^^^^
|
||||
|
||||
error: aborting due to 1 previous error
|
||||
|
||||
|
|
@ -1,9 +1,8 @@
|
|||
// Repro for <https://github.com/rust-lang/rust/issues/90696#issuecomment-963375847>.
|
||||
//@ check-pass
|
||||
//@ edition: 2021
|
||||
//@ revisions: assumptions no_assumptions
|
||||
//@[assumptions] compile-flags: -Zhigher-ranked-assumptions
|
||||
//@[assumptions] check-pass
|
||||
//@[no_assumptions] known-bug: #110338
|
||||
|
||||
#![allow(dropping_copy_types)]
|
||||
|
||||
|
|
|
|||
|
|
@ -8,8 +8,8 @@ extern "C" {
|
|||
}
|
||||
|
||||
const _SIZE: usize = unsafe { size_of_val(&4 as *const i32 as *const Opaque) };
|
||||
//~^ ERROR `extern type` does not have known layout
|
||||
//~^ ERROR: the size for values of type `Opaque` cannot be known
|
||||
const _ALIGN: usize = unsafe { align_of_val(&4 as *const i32 as *const Opaque) };
|
||||
//~^ ERROR `extern type` does not have known layout
|
||||
//~^ ERROR: the size for values of type `Opaque` cannot be known
|
||||
|
||||
fn main() {}
|
||||
|
|
|
|||
|
|
@ -1,15 +1,39 @@
|
|||
error[E0080]: `extern type` does not have known layout
|
||||
--> $DIR/const-size_of_val-align_of_val-extern-type.rs:10:31
|
||||
error[E0277]: the size for values of type `Opaque` cannot be known
|
||||
--> $DIR/const-size_of_val-align_of_val-extern-type.rs:10:43
|
||||
|
|
||||
LL | const _SIZE: usize = unsafe { size_of_val(&4 as *const i32 as *const Opaque) };
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ evaluation of `_SIZE` failed here
|
||||
| ----------- ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `MetaSized` is not implemented for `Opaque`
|
||||
| |
|
||||
| required by a bound introduced by this call
|
||||
|
|
||||
= note: the trait bound `Opaque: MetaSized` is not satisfied
|
||||
note: required by a bound in `std::intrinsics::size_of_val`
|
||||
--> $SRC_DIR/core/src/intrinsics/mod.rs:LL:COL
|
||||
help: consider borrowing here
|
||||
|
|
||||
LL | const _SIZE: usize = unsafe { size_of_val(&(&4 as *const i32 as *const Opaque)) };
|
||||
| ++ +
|
||||
LL | const _SIZE: usize = unsafe { size_of_val(&mut (&4 as *const i32 as *const Opaque)) };
|
||||
| ++++++ +
|
||||
|
||||
error[E0080]: `extern type` does not have known layout
|
||||
--> $DIR/const-size_of_val-align_of_val-extern-type.rs:12:32
|
||||
error[E0277]: the size for values of type `Opaque` cannot be known
|
||||
--> $DIR/const-size_of_val-align_of_val-extern-type.rs:12:45
|
||||
|
|
||||
LL | const _ALIGN: usize = unsafe { align_of_val(&4 as *const i32 as *const Opaque) };
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ evaluation of `_ALIGN` failed here
|
||||
| ------------ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `MetaSized` is not implemented for `Opaque`
|
||||
| |
|
||||
| required by a bound introduced by this call
|
||||
|
|
||||
= note: the trait bound `Opaque: MetaSized` is not satisfied
|
||||
note: required by a bound in `std::intrinsics::align_of_val`
|
||||
--> $SRC_DIR/core/src/intrinsics/mod.rs:LL:COL
|
||||
help: consider borrowing here
|
||||
|
|
||||
LL | const _ALIGN: usize = unsafe { align_of_val(&(&4 as *const i32 as *const Opaque)) };
|
||||
| ++ +
|
||||
LL | const _ALIGN: usize = unsafe { align_of_val(&mut (&4 as *const i32 as *const Opaque)) };
|
||||
| ++++++ +
|
||||
|
||||
error: aborting due to 2 previous errors
|
||||
|
||||
For more information about this error, try `rustc --explain E0080`.
|
||||
For more information about this error, try `rustc --explain E0277`.
|
||||
|
|
|
|||
10
tests/ui/contracts/async-fn-contract-ice-145333.rs
Normal file
10
tests/ui/contracts/async-fn-contract-ice-145333.rs
Normal file
|
|
@ -0,0 +1,10 @@
|
|||
//@ compile-flags: --crate-type=lib
|
||||
//@ edition: 2021
|
||||
#![feature(contracts)]
|
||||
//~^ WARN the feature `contracts` is incomplete
|
||||
|
||||
#[core::contracts::ensures(|ret| *ret)]
|
||||
//~^ ERROR contract annotations are not yet supported on async or gen functions
|
||||
async fn _always_true(b: bool) -> bool {
|
||||
b
|
||||
}
|
||||
17
tests/ui/contracts/async-fn-contract-ice-145333.stderr
Normal file
17
tests/ui/contracts/async-fn-contract-ice-145333.stderr
Normal file
|
|
@ -0,0 +1,17 @@
|
|||
error: contract annotations are not yet supported on async or gen functions
|
||||
--> $DIR/async-fn-contract-ice-145333.rs:6:1
|
||||
|
|
||||
LL | #[core::contracts::ensures(|ret| *ret)]
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
warning: the feature `contracts` is incomplete and may not be safe to use and/or cause compiler crashes
|
||||
--> $DIR/async-fn-contract-ice-145333.rs:3:12
|
||||
|
|
||||
LL | #![feature(contracts)]
|
||||
| ^^^^^^^^^
|
||||
|
|
||||
= note: see issue #128044 <https://github.com/rust-lang/rust/issues/128044> for more information
|
||||
= note: `#[warn(incomplete_features)]` on by default
|
||||
|
||||
error: aborting due to 1 previous error; 1 warning emitted
|
||||
|
||||
|
|
@ -9,7 +9,8 @@ trait Bop {
|
|||
|
||||
fn bop<T: Bop + ?Sized>() {
|
||||
let _ = <T as Bop>::Bar::default();
|
||||
//~^ ERROR: trait bounds were not satisfied
|
||||
//~^ ERROR: the size for values of type `T` cannot be known at compilation time
|
||||
//~| ERROR: the size for values of type `T` cannot be known at compilation time
|
||||
//~| ERROR: the size for values of type `T` cannot be known at compilation time
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -24,21 +24,58 @@ help: consider relaxing the implicit `Sized` restriction
|
|||
LL | type Bar: Default + ?Sized
|
||||
| ++++++++
|
||||
|
||||
error[E0599]: the function or associated item `default` exists for associated type `<T as Bop>::Bar`, but its trait bounds were not satisfied
|
||||
--> $DIR/assoc_type_bounds_sized_used.rs:11:30
|
||||
error[E0277]: the size for values of type `T` cannot be known at compilation time
|
||||
--> $DIR/assoc_type_bounds_sized_used.rs:11:13
|
||||
|
|
||||
LL | fn bop<T: Bop + ?Sized>() {
|
||||
| - this type parameter needs to be `Sized`
|
||||
LL | let _ = <T as Bop>::Bar::default();
|
||||
| ^^^^^^^ function or associated item cannot be called on `<T as Bop>::Bar` due to unsatisfied trait bounds
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time
|
||||
|
|
||||
= note: the following trait bounds were not satisfied:
|
||||
`T: Sized`
|
||||
which is required by `<T as Bop>::Bar: Default`
|
||||
help: consider restricting the type parameter to satisfy the trait bound
|
||||
note: required by a bound in `Bop::Bar`
|
||||
--> $DIR/assoc_type_bounds_sized_used.rs:7:15
|
||||
|
|
||||
LL | fn bop<T: Bop + ?Sized>() where T: Sized {
|
||||
| ++++++++++++++
|
||||
LL | type Bar: Default
|
||||
| --- required by a bound in this associated type
|
||||
LL | where
|
||||
LL | Self: Sized;
|
||||
| ^^^^^ required by this bound in `Bop::Bar`
|
||||
help: consider removing the `?Sized` bound to make the type parameter `Sized`
|
||||
|
|
||||
LL - fn bop<T: Bop + ?Sized>() {
|
||||
LL + fn bop<T: Bop>() {
|
||||
|
|
||||
help: consider relaxing the implicit `Sized` restriction
|
||||
|
|
||||
LL | type Bar: Default + ?Sized
|
||||
| ++++++++
|
||||
|
||||
error: aborting due to 2 previous errors
|
||||
error[E0277]: the size for values of type `T` cannot be known at compilation time
|
||||
--> $DIR/assoc_type_bounds_sized_used.rs:11:13
|
||||
|
|
||||
LL | fn bop<T: Bop + ?Sized>() {
|
||||
| - this type parameter needs to be `Sized`
|
||||
LL | let _ = <T as Bop>::Bar::default();
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time
|
||||
|
|
||||
note: required by a bound in `Bop::Bar`
|
||||
--> $DIR/assoc_type_bounds_sized_used.rs:7:15
|
||||
|
|
||||
LL | type Bar: Default
|
||||
| --- required by a bound in this associated type
|
||||
LL | where
|
||||
LL | Self: Sized;
|
||||
| ^^^^^ required by this bound in `Bop::Bar`
|
||||
help: consider removing the `?Sized` bound to make the type parameter `Sized`
|
||||
|
|
||||
LL - fn bop<T: Bop + ?Sized>() {
|
||||
LL + fn bop<T: Bop>() {
|
||||
|
|
||||
help: consider relaxing the implicit `Sized` restriction
|
||||
|
|
||||
LL | type Bar: Default + ?Sized
|
||||
| ++++++++
|
||||
|
||||
Some errors have detailed explanations: E0277, E0599.
|
||||
For more information about an error, try `rustc --explain E0277`.
|
||||
error: aborting due to 3 previous errors
|
||||
|
||||
For more information about this error, try `rustc --explain E0277`.
|
||||
|
|
|
|||
5
tests/ui/extern/extern-types-size_of_val.rs
vendored
5
tests/ui/extern/extern-types-size_of_val.rs
vendored
|
|
@ -1,8 +1,9 @@
|
|||
//@ check-pass
|
||||
#![feature(extern_types)]
|
||||
|
||||
use std::mem::{align_of_val, size_of_val};
|
||||
|
||||
// Check that calls to `size_of_val` and `align_of_val` with extern types are not accepted
|
||||
|
||||
extern "C" {
|
||||
type A;
|
||||
}
|
||||
|
|
@ -11,5 +12,7 @@ fn main() {
|
|||
let x: &A = unsafe { &*(1usize as *const A) };
|
||||
|
||||
size_of_val(x);
|
||||
//~^ ERROR: the size for values of type `A` cannot be known
|
||||
align_of_val(x);
|
||||
//~^ ERROR: the size for values of type `A` cannot be known
|
||||
}
|
||||
|
|
|
|||
39
tests/ui/extern/extern-types-size_of_val.stderr
vendored
Normal file
39
tests/ui/extern/extern-types-size_of_val.stderr
vendored
Normal file
|
|
@ -0,0 +1,39 @@
|
|||
error[E0277]: the size for values of type `A` cannot be known
|
||||
--> $DIR/extern-types-size_of_val.rs:14:17
|
||||
|
|
||||
LL | size_of_val(x);
|
||||
| ----------- ^ the trait `MetaSized` is not implemented for `A`
|
||||
| |
|
||||
| required by a bound introduced by this call
|
||||
|
|
||||
= note: the trait bound `A: MetaSized` is not satisfied
|
||||
note: required by a bound in `std::mem::size_of_val`
|
||||
--> $SRC_DIR/core/src/mem/mod.rs:LL:COL
|
||||
help: consider borrowing here
|
||||
|
|
||||
LL | size_of_val(&x);
|
||||
| +
|
||||
LL | size_of_val(&mut x);
|
||||
| ++++
|
||||
|
||||
error[E0277]: the size for values of type `A` cannot be known
|
||||
--> $DIR/extern-types-size_of_val.rs:16:18
|
||||
|
|
||||
LL | align_of_val(x);
|
||||
| ------------ ^ the trait `MetaSized` is not implemented for `A`
|
||||
| |
|
||||
| required by a bound introduced by this call
|
||||
|
|
||||
= note: the trait bound `A: MetaSized` is not satisfied
|
||||
note: required by a bound in `std::mem::align_of_val`
|
||||
--> $SRC_DIR/core/src/mem/mod.rs:LL:COL
|
||||
help: consider borrowing here
|
||||
|
|
||||
LL | align_of_val(&x);
|
||||
| +
|
||||
LL | align_of_val(&mut x);
|
||||
| ++++
|
||||
|
||||
error: aborting due to 2 previous errors
|
||||
|
||||
For more information about this error, try `rustc --explain E0277`.
|
||||
2
tests/ui/extern/extern-types-unsized.rs
vendored
2
tests/ui/extern/extern-types-unsized.rs
vendored
|
|
@ -27,7 +27,9 @@ fn main() {
|
|||
|
||||
assert_sized::<Bar<A>>();
|
||||
//~^ ERROR the size for values of type
|
||||
//~| ERROR the size for values of type `A` cannot be known
|
||||
|
||||
assert_sized::<Bar<Bar<A>>>();
|
||||
//~^ ERROR the size for values of type
|
||||
//~| ERROR the size for values of type `A` cannot be known
|
||||
}
|
||||
|
|
|
|||
30
tests/ui/extern/extern-types-unsized.stderr
vendored
30
tests/ui/extern/extern-types-unsized.stderr
vendored
|
|
@ -59,8 +59,21 @@ help: consider relaxing the implicit `Sized` restriction
|
|||
LL | fn assert_sized<T: ?Sized>() {}
|
||||
| ++++++++
|
||||
|
||||
error[E0277]: the size for values of type `A` cannot be known
|
||||
--> $DIR/extern-types-unsized.rs:28:20
|
||||
|
|
||||
LL | assert_sized::<Bar<A>>();
|
||||
| ^^^^^^ doesn't have a known size
|
||||
|
|
||||
= help: the trait `MetaSized` is not implemented for `A`
|
||||
note: required by a bound in `Bar`
|
||||
--> $DIR/extern-types-unsized.rs:14:12
|
||||
|
|
||||
LL | struct Bar<T: ?Sized> {
|
||||
| ^ required by this bound in `Bar`
|
||||
|
||||
error[E0277]: the size for values of type `A` cannot be known at compilation time
|
||||
--> $DIR/extern-types-unsized.rs:31:20
|
||||
--> $DIR/extern-types-unsized.rs:32:20
|
||||
|
|
||||
LL | assert_sized::<Bar<Bar<A>>>();
|
||||
| ^^^^^^^^^^^ doesn't have a size known at compile-time
|
||||
|
|
@ -81,6 +94,19 @@ help: consider relaxing the implicit `Sized` restriction
|
|||
LL | fn assert_sized<T: ?Sized>() {}
|
||||
| ++++++++
|
||||
|
||||
error: aborting due to 4 previous errors
|
||||
error[E0277]: the size for values of type `A` cannot be known
|
||||
--> $DIR/extern-types-unsized.rs:32:20
|
||||
|
|
||||
LL | assert_sized::<Bar<Bar<A>>>();
|
||||
| ^^^^^^^^^^^ doesn't have a known size
|
||||
|
|
||||
= help: the trait `MetaSized` is not implemented for `A`
|
||||
note: required by a bound in `Bar`
|
||||
--> $DIR/extern-types-unsized.rs:14:12
|
||||
|
|
||||
LL | struct Bar<T: ?Sized> {
|
||||
| ^ required by this bound in `Bar`
|
||||
|
||||
error: aborting due to 6 previous errors
|
||||
|
||||
For more information about this error, try `rustc --explain E0277`.
|
||||
|
|
|
|||
4
tests/ui/extern/unsized-extern-derefmove.rs
vendored
4
tests/ui/extern/unsized-extern-derefmove.rs
vendored
|
|
@ -7,10 +7,14 @@ extern "C" {
|
|||
}
|
||||
|
||||
unsafe fn make_device() -> Box<Device> {
|
||||
//~^ ERROR the size for values of type `Device` cannot be known
|
||||
Box::from_raw(0 as *mut _)
|
||||
//~^ ERROR the size for values of type `Device` cannot be known
|
||||
//~| ERROR the size for values of type `Device` cannot be known
|
||||
}
|
||||
|
||||
fn main() {
|
||||
let d: Device = unsafe { *make_device() };
|
||||
//~^ ERROR the size for values of type `Device` cannot be known
|
||||
//~| ERROR the size for values of type `Device` cannot be known
|
||||
}
|
||||
|
|
|
|||
52
tests/ui/extern/unsized-extern-derefmove.stderr
vendored
52
tests/ui/extern/unsized-extern-derefmove.stderr
vendored
|
|
@ -1,5 +1,43 @@
|
|||
error[E0277]: the size for values of type `Device` cannot be known
|
||||
--> $DIR/unsized-extern-derefmove.rs:9:28
|
||||
|
|
||||
LL | unsafe fn make_device() -> Box<Device> {
|
||||
| ^^^^^^^^^^^ doesn't have a known size
|
||||
|
|
||||
= help: the trait `MetaSized` is not implemented for `Device`
|
||||
note: required by a bound in `Box`
|
||||
--> $SRC_DIR/alloc/src/boxed.rs:LL:COL
|
||||
|
||||
error[E0277]: the size for values of type `Device` cannot be known
|
||||
--> $DIR/unsized-extern-derefmove.rs:11:19
|
||||
|
|
||||
LL | Box::from_raw(0 as *mut _)
|
||||
| ------------- ^^^^^^^^^^^ the trait `MetaSized` is not implemented for `Device`
|
||||
| |
|
||||
| required by a bound introduced by this call
|
||||
|
|
||||
= note: the trait bound `Device: MetaSized` is not satisfied
|
||||
note: required by a bound in `Box::<T>::from_raw`
|
||||
--> $SRC_DIR/alloc/src/boxed.rs:LL:COL
|
||||
help: consider borrowing here
|
||||
|
|
||||
LL | Box::from_raw(&(0 as *mut _))
|
||||
| ++ +
|
||||
LL | Box::from_raw(&mut (0 as *mut _))
|
||||
| ++++++ +
|
||||
|
||||
error[E0277]: the size for values of type `Device` cannot be known
|
||||
--> $DIR/unsized-extern-derefmove.rs:11:5
|
||||
|
|
||||
LL | Box::from_raw(0 as *mut _)
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^ doesn't have a known size
|
||||
|
|
||||
= help: the trait `MetaSized` is not implemented for `Device`
|
||||
note: required by a bound in `Box`
|
||||
--> $SRC_DIR/alloc/src/boxed.rs:LL:COL
|
||||
|
||||
error[E0277]: the size for values of type `Device` cannot be known at compilation time
|
||||
--> $DIR/unsized-extern-derefmove.rs:14:9
|
||||
--> $DIR/unsized-extern-derefmove.rs:17:9
|
||||
|
|
||||
LL | let d: Device = unsafe { *make_device() };
|
||||
| ^ doesn't have a size known at compile-time
|
||||
|
|
@ -11,6 +49,16 @@ help: consider borrowing here
|
|||
LL | let d: &Device = unsafe { *make_device() };
|
||||
| +
|
||||
|
||||
error: aborting due to 1 previous error
|
||||
error[E0277]: the size for values of type `Device` cannot be known
|
||||
--> $DIR/unsized-extern-derefmove.rs:17:31
|
||||
|
|
||||
LL | let d: Device = unsafe { *make_device() };
|
||||
| ^^^^^^^^^^^^^ doesn't have a known size
|
||||
|
|
||||
= help: the trait `MetaSized` is not implemented for `Device`
|
||||
note: required by a bound in `Box`
|
||||
--> $SRC_DIR/alloc/src/boxed.rs:LL:COL
|
||||
|
||||
error: aborting due to 5 previous errors
|
||||
|
||||
For more information about this error, try `rustc --explain E0277`.
|
||||
|
|
|
|||
|
|
@ -1,24 +0,0 @@
|
|||
error: lifetime bound not satisfied
|
||||
--> $DIR/higher-ranked-coroutine-param-outlives-2.rs:14:5
|
||||
|
|
||||
LL | / async { // a coroutine checked for autotrait impl `Send`
|
||||
LL | | let x = None::<I::Future<'_, '_>>; // a type referencing GAT
|
||||
LL | | async {}.await; // a yield point
|
||||
LL | | }
|
||||
| |_____^
|
||||
|
|
||||
= note: this is a known limitation that will be removed in the future (see issue #100013 <https://github.com/rust-lang/rust/issues/100013> for more information)
|
||||
|
||||
error: lifetime bound not satisfied
|
||||
--> $DIR/higher-ranked-coroutine-param-outlives-2.rs:21:5
|
||||
|
|
||||
LL | / async { // a coroutine checked for autotrait impl `Send`
|
||||
LL | | let x = None::<I::Future<'a, 'b>>; // a type referencing GAT
|
||||
LL | | async {}.await; // a yield point
|
||||
LL | | }
|
||||
| |_____^
|
||||
|
|
||||
= note: this is a known limitation that will be removed in the future (see issue #100013 <https://github.com/rust-lang/rust/issues/100013> for more information)
|
||||
|
||||
error: aborting due to 2 previous errors
|
||||
|
||||
|
|
@ -1,8 +1,7 @@
|
|||
//@ check-pass
|
||||
//@ edition: 2021
|
||||
//@ revisions: assumptions no_assumptions
|
||||
//@[assumptions] compile-flags: -Zhigher-ranked-assumptions
|
||||
//@[assumptions] check-pass
|
||||
//@[no_assumptions] known-bug: #110338
|
||||
|
||||
pub trait FutureIterator {
|
||||
type Future<'s, 'cx>: Send
|
||||
|
|
|
|||
|
|
@ -1,8 +0,0 @@
|
|||
error: `C` does not live long enough
|
||||
--> $DIR/higher-ranked-coroutine-param-outlives.rs:21:5
|
||||
|
|
||||
LL | async move { c.connect().await }
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
error: aborting due to 1 previous error
|
||||
|
||||
|
|
@ -1,8 +1,7 @@
|
|||
//@ check-pass
|
||||
//@ edition:2018
|
||||
//@ revisions: assumptions no_assumptions
|
||||
//@[assumptions] compile-flags: -Zhigher-ranked-assumptions
|
||||
//@[assumptions] check-pass
|
||||
//@[no_assumptions] known-bug: #110338
|
||||
|
||||
use std::future::Future;
|
||||
|
||||
|
|
|
|||
|
|
@ -0,0 +1,14 @@
|
|||
error[E0282]: type annotations needed for `<X as Trait<'static>>::Out<_>`
|
||||
--> $DIR/norm-before-method-resolution-opaque-type.rs:25:9
|
||||
|
|
||||
LL | let x = *x;
|
||||
| ^
|
||||
|
|
||||
help: consider giving `x` an explicit type, where the placeholders `_` are specified
|
||||
|
|
||||
LL | let x: <_ as Trait<'static>>::Out<_> = *x;
|
||||
| +++++++++++++++++++++++++++++++
|
||||
|
||||
error: aborting due to 1 previous error
|
||||
|
||||
For more information about this error, try `rustc --explain E0282`.
|
||||
|
|
@ -1,5 +1,5 @@
|
|||
error[E0507]: cannot move out of `*x` which is behind a shared reference
|
||||
--> $DIR/norm-before-method-resolution-opaque-type.rs:22:13
|
||||
--> $DIR/norm-before-method-resolution-opaque-type.rs:25:13
|
||||
|
|
||||
LL | let x = *x;
|
||||
| ^^ move occurs because `*x` has type `<X as Trait<'_>>::Out<Foo>`, which does not implement the `Copy` trait
|
||||
|
|
|
|||
|
|
@ -1,6 +1,9 @@
|
|||
//@ revisions: old next
|
||||
//@[next] compile-flags: -Znext-solver
|
||||
//@[next] check-pass
|
||||
|
||||
// In the next solver, the opaque was previously defined by using the where-bound when checking
|
||||
// whether the alias is `Sized`, constraining the opaque. Instead, the alias-bound is now used,
|
||||
// which means the opaque is never constrained.
|
||||
|
||||
#![feature(type_alias_impl_trait)]
|
||||
trait Trait<'a> {
|
||||
|
|
@ -20,6 +23,7 @@ where
|
|||
for<'a> <X as Trait<'a>>::Out<()>: Copy,
|
||||
{
|
||||
let x = *x; //[old]~ ERROR: cannot move out of `*x`
|
||||
//[next]~^ ERROR: type annotations needed
|
||||
todo!();
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -17,3 +17,4 @@ impl<C: ?Sized> A for u8 { //~ ERROR: the type parameter `C` is not constrained
|
|||
#[rustc_layout(debug)]
|
||||
struct S([u8; <u8 as A>::B]);
|
||||
//~^ ERROR: the type has an unknown layout
|
||||
//~| ERROR: type annotations needed
|
||||
|
|
|
|||
|
|
@ -4,12 +4,19 @@ error[E0207]: the type parameter `C` is not constrained by the impl trait, self
|
|||
LL | impl<C: ?Sized> A for u8 {
|
||||
| ^ unconstrained type parameter
|
||||
|
||||
error[E0282]: type annotations needed
|
||||
--> $DIR/unconstrained-param-ice-137308.rs:18:16
|
||||
|
|
||||
LL | struct S([u8; <u8 as A>::B]);
|
||||
| ^^ cannot infer type for type parameter `C`
|
||||
|
||||
error: the type has an unknown layout
|
||||
--> $DIR/unconstrained-param-ice-137308.rs:18:1
|
||||
|
|
||||
LL | struct S([u8; <u8 as A>::B]);
|
||||
| ^^^^^^^^
|
||||
|
||||
error: aborting due to 2 previous errors
|
||||
error: aborting due to 3 previous errors
|
||||
|
||||
For more information about this error, try `rustc --explain E0207`.
|
||||
Some errors have detailed explanations: E0207, E0282.
|
||||
For more information about an error, try `rustc --explain E0207`.
|
||||
|
|
|
|||
|
|
@ -1,13 +1,15 @@
|
|||
error[E0499]: cannot borrow `*t` as mutable more than once at a time
|
||||
--> $DIR/lending-iterator-sanity-checks.rs:19:19
|
||||
|
|
||||
LL | fn use_live<T: LendingIterator>(t: &mut T) -> Option<(T::Item<'_>, T::Item<'_>)> {
|
||||
| - let's call the lifetime of this reference `'1`
|
||||
LL | let Some(i) = t.next() else { return None };
|
||||
| - first mutable borrow occurs here
|
||||
LL | let Some(j) = t.next() else { return None };
|
||||
| ^ second mutable borrow occurs here
|
||||
...
|
||||
LL | }
|
||||
| - first borrow might be used here, when `i` is dropped and runs the destructor for type `<T as LendingIterator>::Item<'_>`
|
||||
LL | Some((i, j))
|
||||
| ------------ returning this value requires that `*t` is borrowed for `'1`
|
||||
|
||||
error[E0499]: cannot borrow `*t` as mutable more than once at a time
|
||||
--> $DIR/lending-iterator-sanity-checks.rs:31:13
|
||||
|
|
|
|||
21
tests/ui/sized-hierarchy/bound-on-assoc-type-projection-1.rs
Normal file
21
tests/ui/sized-hierarchy/bound-on-assoc-type-projection-1.rs
Normal file
|
|
@ -0,0 +1,21 @@
|
|||
//@ check-pass
|
||||
//@ compile-flags: --crate-type=lib
|
||||
//@ revisions: old next
|
||||
//@[next] compile-flags: -Znext-solver
|
||||
|
||||
use std::marker::PhantomData;
|
||||
|
||||
pub trait ZeroMapKV<'a> {
|
||||
type Container;
|
||||
}
|
||||
|
||||
pub trait ZeroFrom<'zf, C: ?Sized> {}
|
||||
|
||||
pub struct ZeroMap<'a, K: ZeroMapKV<'a>>(PhantomData<&'a K>);
|
||||
|
||||
impl<'zf, 's, K> ZeroFrom<'zf, ZeroMap<'s, K>> for ZeroMap<'zf, K>
|
||||
where
|
||||
K: for<'b> ZeroMapKV<'b>,
|
||||
<K as ZeroMapKV<'zf>>::Container: ZeroFrom<'zf, <K as ZeroMapKV<'s>>::Container>,
|
||||
{
|
||||
}
|
||||
|
|
@ -1,17 +0,0 @@
|
|||
error[E0308]: mismatched types
|
||||
--> $DIR/incomplete-inference-issue-143992.rs:30:28
|
||||
|
|
||||
LL | let _x = T::Assoc::new(());
|
||||
| ------------- ^^ expected `[u32; 1]`, found `()`
|
||||
| |
|
||||
| arguments to this function are incorrect
|
||||
|
|
||||
note: associated function defined here
|
||||
--> $DIR/incomplete-inference-issue-143992.rs:21:8
|
||||
|
|
||||
LL | fn new(r: R) -> R {
|
||||
| ^^^ ----
|
||||
|
||||
error: aborting due to 1 previous error
|
||||
|
||||
For more information about this error, try `rustc --explain E0308`.
|
||||
|
|
@ -1,17 +0,0 @@
|
|||
error[E0308]: mismatched types
|
||||
--> $DIR/incomplete-inference-issue-143992.rs:30:28
|
||||
|
|
||||
LL | let _x = T::Assoc::new(());
|
||||
| ------------- ^^ expected `[u32; 1]`, found `()`
|
||||
| |
|
||||
| arguments to this function are incorrect
|
||||
|
|
||||
note: associated function defined here
|
||||
--> $DIR/incomplete-inference-issue-143992.rs:21:8
|
||||
|
|
||||
LL | fn new(r: R) -> R {
|
||||
| ^^^ ----
|
||||
|
||||
error: aborting due to 1 previous error
|
||||
|
||||
For more information about this error, try `rustc --explain E0308`.
|
||||
|
|
@ -1,12 +1,8 @@
|
|||
//@ check-pass
|
||||
//@ compile-flags: --crate-type=lib
|
||||
//@ revisions: current next current_sized_hierarchy next_sized_hierarchy
|
||||
//@ revisions: current next
|
||||
//@ ignore-compare-mode-next-solver (explicit revisions)
|
||||
//@[current] check-pass
|
||||
//@[next] check-pass
|
||||
//@[next] compile-flags: -Znext-solver
|
||||
//@[next_sized_hierarchy] compile-flags: -Znext-solver
|
||||
|
||||
#![cfg_attr(any(current_sized_hierarchy, next_sized_hierarchy), feature(sized_hierarchy))]
|
||||
|
||||
// Test that we avoid incomplete inference when normalizing. Without this,
|
||||
// `Trait`'s implicit `MetaSized` supertrait requires proving `T::Assoc<_>: MetaSized`
|
||||
|
|
@ -28,6 +24,4 @@ where
|
|||
T::Assoc<[u32; 1]>: Clone,
|
||||
{
|
||||
let _x = T::Assoc::new(());
|
||||
//[next_sized_hierarchy]~^ ERROR mismatched types
|
||||
//[current_sized_hierarchy]~^^ ERROR mismatched types
|
||||
}
|
||||
|
|
|
|||
45
tests/ui/sized-hierarchy/overflow.current.stderr
Normal file
45
tests/ui/sized-hierarchy/overflow.current.stderr
Normal file
|
|
@ -0,0 +1,45 @@
|
|||
error[E0275]: overflow evaluating the requirement `Element: MetaSized`
|
||||
--> $DIR/overflow.rs:17:16
|
||||
|
|
||||
LL | struct Element(<Box<Box<Element>> as ParseTokens>::Output);
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
note: required for `Box<Element>` to implement `ParseTokens`
|
||||
--> $DIR/overflow.rs:13:31
|
||||
|
|
||||
LL | impl<T: ParseTokens + ?Sized> ParseTokens for Box<T> {
|
||||
| - ^^^^^^^^^^^ ^^^^^^
|
||||
| |
|
||||
| unsatisfied trait bound introduced here
|
||||
= note: 1 redundant requirement hidden
|
||||
= note: required for `Box<Box<Element>>` to implement `ParseTokens`
|
||||
|
||||
error[E0275]: overflow evaluating the requirement `Box<Element>: ParseTokens`
|
||||
--> $DIR/overflow.rs:19:22
|
||||
|
|
||||
LL | impl ParseTokens for Element {
|
||||
| ^^^^^^^
|
||||
|
|
||||
note: required for `Box<Box<Element>>` to implement `ParseTokens`
|
||||
--> $DIR/overflow.rs:13:31
|
||||
|
|
||||
LL | impl<T: ParseTokens + ?Sized> ParseTokens for Box<T> {
|
||||
| ----------- ^^^^^^^^^^^ ^^^^^^
|
||||
| |
|
||||
| unsatisfied trait bound introduced here
|
||||
note: required because it appears within the type `Element`
|
||||
--> $DIR/overflow.rs:17:8
|
||||
|
|
||||
LL | struct Element(<Box<Box<Element>> as ParseTokens>::Output);
|
||||
| ^^^^^^^
|
||||
note: required by a bound in `ParseTokens`
|
||||
--> $DIR/overflow.rs:10:1
|
||||
|
|
||||
LL | / trait ParseTokens {
|
||||
LL | | type Output;
|
||||
LL | | }
|
||||
| |_^ required by this bound in `ParseTokens`
|
||||
|
||||
error: aborting due to 2 previous errors
|
||||
|
||||
For more information about this error, try `rustc --explain E0275`.
|
||||
|
|
@ -1,13 +1,10 @@
|
|||
//@ compile-flags: --crate-type=lib
|
||||
//@ revisions: current next
|
||||
//@ ignore-compare-mode-next-solver (explicit revisions)
|
||||
//@[current] check-pass
|
||||
//@[current] check-fail
|
||||
//@[next] check-pass
|
||||
//@[next] compile-flags: -Znext-solver
|
||||
|
||||
// FIXME(sized_hierarchy): this is expected to fail in the old solver when there
|
||||
// isn't a temporary revert of the `sized_hierarchy` feature
|
||||
|
||||
use std::marker::PhantomData;
|
||||
|
||||
trait ParseTokens {
|
||||
|
|
@ -18,6 +15,8 @@ impl<T: ParseTokens + ?Sized> ParseTokens for Box<T> {
|
|||
}
|
||||
|
||||
struct Element(<Box<Box<Element>> as ParseTokens>::Output);
|
||||
//[current]~^ ERROR: overflow
|
||||
impl ParseTokens for Element {
|
||||
//[current]~^ ERROR: overflow
|
||||
type Output = ();
|
||||
}
|
||||
|
|
|
|||
30
tests/ui/sized-hierarchy/prefer-non-nested-alias-bound.rs
Normal file
30
tests/ui/sized-hierarchy/prefer-non-nested-alias-bound.rs
Normal file
|
|
@ -0,0 +1,30 @@
|
|||
//@ check-pass
|
||||
//@ compile-flags: --crate-type=lib
|
||||
//@ revisions: current next
|
||||
//@ ignore-compare-mode-next-solver (explicit revisions)
|
||||
//@[next] compile-flags: -Znext-solver
|
||||
|
||||
// Since #120752, also get alias-bound candidates from a nested self-type, so prefering
|
||||
// alias-bound over where-bound candidates can be incorrect. This test checks that case and that
|
||||
// we prefer non-nested alias-bound candidates over where-bound candidates over nested alias-bound
|
||||
// candidates.
|
||||
|
||||
trait OtherTrait<'a> {
|
||||
type Assoc: ?Sized;
|
||||
}
|
||||
|
||||
trait Trait
|
||||
where
|
||||
<Self::Assoc as OtherTrait<'static>>::Assoc: Sized,
|
||||
{
|
||||
type Assoc: for<'a> OtherTrait<'a>;
|
||||
}
|
||||
|
||||
fn impls_sized<T: Sized>() {}
|
||||
fn foo<'a, T>()
|
||||
where
|
||||
T: Trait,
|
||||
for<'hr> <T::Assoc as OtherTrait<'hr>>::Assoc: Sized,
|
||||
{
|
||||
impls_sized::<<T::Assoc as OtherTrait<'a>>::Assoc>();
|
||||
}
|
||||
|
|
@ -4,6 +4,10 @@
|
|||
|
||||
#![feature(trivial_bounds)]
|
||||
|
||||
// we use identity instead of drop because the presence of [const] Destruct means that there
|
||||
// are additional bounds on the function, which result in additional errors
|
||||
use std::convert::identity;
|
||||
|
||||
trait Foo {
|
||||
type Item: Copy
|
||||
where
|
||||
|
|
@ -21,7 +25,7 @@ impl Foo for () {
|
|||
|
||||
fn main() {
|
||||
let x = String::from("hello, world");
|
||||
drop(<() as Foo>::copy_me(&x));
|
||||
let _ = identity(<() as Foo>::copy_me(&x));
|
||||
//~^ ERROR overflow evaluating the requirement `String <: <() as Foo>::Item`
|
||||
//~| ERROR overflow evaluating the requirement `<() as Foo>::Item well-formed`
|
||||
//~| ERROR overflow evaluating the requirement `&<() as Foo>::Item well-formed`
|
||||
|
|
|
|||
|
|
@ -1,11 +1,11 @@
|
|||
error[E0275]: overflow evaluating the requirement `String: Copy`
|
||||
--> $DIR/alias-bound-unsound.rs:18:38
|
||||
--> $DIR/alias-bound-unsound.rs:22:38
|
||||
|
|
||||
LL | type Item = String where String: Copy;
|
||||
| ^^^^
|
||||
|
|
||||
note: the requirement `String: Copy` appears on the `impl`'s associated type `Item` but not on the corresponding trait's associated type
|
||||
--> $DIR/alias-bound-unsound.rs:8:10
|
||||
--> $DIR/alias-bound-unsound.rs:12:10
|
||||
|
|
||||
LL | trait Foo {
|
||||
| --- in this trait
|
||||
|
|
@ -13,50 +13,50 @@ LL | type Item: Copy
|
|||
| ^^^^ this trait's associated type doesn't have the requirement `String: Copy`
|
||||
|
||||
error[E0275]: overflow evaluating the requirement `String <: <() as Foo>::Item`
|
||||
--> $DIR/alias-bound-unsound.rs:24:31
|
||||
--> $DIR/alias-bound-unsound.rs:28:43
|
||||
|
|
||||
LL | drop(<() as Foo>::copy_me(&x));
|
||||
| ^^
|
||||
LL | let _ = identity(<() as Foo>::copy_me(&x));
|
||||
| ^^
|
||||
|
||||
error[E0275]: overflow evaluating the requirement `<() as Foo>::Item == _`
|
||||
--> $DIR/alias-bound-unsound.rs:24:10
|
||||
--> $DIR/alias-bound-unsound.rs:28:22
|
||||
|
|
||||
LL | drop(<() as Foo>::copy_me(&x));
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
LL | let _ = identity(<() as Foo>::copy_me(&x));
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
error[E0275]: overflow evaluating the requirement `<() as Foo>::Item == _`
|
||||
--> $DIR/alias-bound-unsound.rs:24:10
|
||||
--> $DIR/alias-bound-unsound.rs:28:22
|
||||
|
|
||||
LL | drop(<() as Foo>::copy_me(&x));
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
LL | let _ = identity(<() as Foo>::copy_me(&x));
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
= note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
|
||||
|
||||
error[E0275]: overflow evaluating the requirement `&<() as Foo>::Item well-formed`
|
||||
--> $DIR/alias-bound-unsound.rs:24:31
|
||||
--> $DIR/alias-bound-unsound.rs:28:43
|
||||
|
|
||||
LL | drop(<() as Foo>::copy_me(&x));
|
||||
| ^^
|
||||
LL | let _ = identity(<() as Foo>::copy_me(&x));
|
||||
| ^^
|
||||
|
||||
error[E0275]: overflow evaluating the requirement `<() as Foo>::Item well-formed`
|
||||
--> $DIR/alias-bound-unsound.rs:24:10
|
||||
--> $DIR/alias-bound-unsound.rs:28:22
|
||||
|
|
||||
LL | drop(<() as Foo>::copy_me(&x));
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
LL | let _ = identity(<() as Foo>::copy_me(&x));
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
error[E0275]: overflow evaluating the requirement `<() as Foo>::Item == _`
|
||||
--> $DIR/alias-bound-unsound.rs:24:10
|
||||
--> $DIR/alias-bound-unsound.rs:28:22
|
||||
|
|
||||
LL | drop(<() as Foo>::copy_me(&x));
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
LL | let _ = identity(<() as Foo>::copy_me(&x));
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
= note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
|
||||
|
||||
error[E0275]: overflow evaluating the requirement `<() as Foo>::Item == _`
|
||||
--> $DIR/alias-bound-unsound.rs:24:31
|
||||
--> $DIR/alias-bound-unsound.rs:28:43
|
||||
|
|
||||
LL | drop(<() as Foo>::copy_me(&x));
|
||||
| ^^
|
||||
LL | let _ = identity(<() as Foo>::copy_me(&x));
|
||||
| ^^
|
||||
|
||||
error: aborting due to 8 previous errors
|
||||
|
||||
|
|
|
|||
|
|
@ -17,6 +17,13 @@ LL | impl<T: Bound, U> Trait<U> for T {
|
|||
| ----- ^^^^^^^^ ^
|
||||
| |
|
||||
| unsatisfied trait bound introduced here
|
||||
note: required by a bound in `Bound`
|
||||
--> $DIR/normalizes-to-is-not-productive.rs:8:1
|
||||
|
|
||||
LL | / trait Bound {
|
||||
LL | | fn method();
|
||||
LL | | }
|
||||
| |_^ required by this bound in `Bound`
|
||||
|
||||
error[E0277]: the trait bound `Foo: Bound` is not satisfied
|
||||
--> $DIR/normalizes-to-is-not-productive.rs:47:19
|
||||
|
|
|
|||
|
|
@ -19,6 +19,23 @@ error[E0275]: overflow evaluating the requirement `<() as A<T>>::Assoc: A<T>`
|
|||
LL | Self::Assoc: A<T>,
|
||||
| ^^^^
|
||||
|
||||
error[E0275]: overflow evaluating the requirement `<() as A<T>>::Assoc: MetaSized`
|
||||
--> $DIR/normalize-param-env-2.rs:24:22
|
||||
|
|
||||
LL | Self::Assoc: A<T>,
|
||||
| ^^^^
|
||||
|
|
||||
note: required by a bound in `A`
|
||||
--> $DIR/normalize-param-env-2.rs:9:1
|
||||
|
|
||||
LL | / trait A<T> {
|
||||
LL | | type Assoc;
|
||||
LL | |
|
||||
LL | | fn f()
|
||||
... |
|
||||
LL | | }
|
||||
| |_^ required by this bound in `A`
|
||||
|
||||
error[E0275]: overflow evaluating the requirement `<() as A<T>>::Assoc well-formed`
|
||||
--> $DIR/normalize-param-env-2.rs:24:22
|
||||
|
|
||||
|
|
@ -46,6 +63,6 @@ LL | where
|
|||
LL | Self::Assoc: A<T>,
|
||||
| ^^^^ required by this bound in `A::f`
|
||||
|
||||
error: aborting due to 5 previous errors
|
||||
error: aborting due to 6 previous errors
|
||||
|
||||
For more information about this error, try `rustc --explain E0275`.
|
||||
|
|
|
|||
|
|
@ -4,6 +4,20 @@ error[E0275]: overflow evaluating the requirement `<T as Trait>::Assoc: Trait`
|
|||
LL | <T as Trait>::Assoc: Trait,
|
||||
| ^^^^^
|
||||
|
||||
error: aborting due to 1 previous error
|
||||
error[E0275]: overflow evaluating the requirement `<T as Trait>::Assoc: MetaSized`
|
||||
--> $DIR/normalize-param-env-4.rs:19:26
|
||||
|
|
||||
LL | <T as Trait>::Assoc: Trait,
|
||||
| ^^^^^
|
||||
|
|
||||
note: required by a bound in `Trait`
|
||||
--> $DIR/normalize-param-env-4.rs:7:1
|
||||
|
|
||||
LL | / trait Trait {
|
||||
LL | | type Assoc;
|
||||
LL | | }
|
||||
| |_^ required by this bound in `Trait`
|
||||
|
||||
error: aborting due to 2 previous errors
|
||||
|
||||
For more information about this error, try `rustc --explain E0275`.
|
||||
|
|
|
|||
|
|
@ -15,6 +15,7 @@ use foo::*;
|
|||
|
||||
fn test() -> impl Sized {
|
||||
<() as Callable>::call()
|
||||
//~^ ERROR type annotations needed
|
||||
}
|
||||
|
||||
fn main() {}
|
||||
|
|
|
|||
|
|
@ -4,6 +4,13 @@ error[E0207]: the type parameter `V` is not constrained by the impl trait, self
|
|||
LL | impl<V: ?Sized> Callable for () {
|
||||
| ^ unconstrained type parameter
|
||||
|
||||
error: aborting due to 1 previous error
|
||||
error[E0282]: type annotations needed
|
||||
--> $DIR/resolve-impl-before-constrain-check.rs:17:6
|
||||
|
|
||||
LL | <() as Callable>::call()
|
||||
| ^^ cannot infer type for type parameter `V`
|
||||
|
||||
For more information about this error, try `rustc --explain E0207`.
|
||||
error: aborting due to 2 previous errors
|
||||
|
||||
Some errors have detailed explanations: E0207, E0282.
|
||||
For more information about an error, try `rustc --explain E0207`.
|
||||
|
|
|
|||
|
|
@ -738,13 +738,15 @@ message_on_reopen = "PR #{number} has been reopened. Pinging @*T-rustdoc*."
|
|||
[notify-zulip."beta-nominated".compiler]
|
||||
required_labels = ["T-compiler"]
|
||||
zulip_stream = 474880 # #t-compiler/backports
|
||||
topic = "#{number}: beta-nominated"
|
||||
topic = "#{number}: beta-backport nomination"
|
||||
message_on_add = [
|
||||
"""\
|
||||
@**channel** PR #{number} "{title}" has been nominated for beta backport.
|
||||
PR #{number} "{title}" fixes a regression.
|
||||
{recipients}, please evaluate nominating this PR for backport.
|
||||
The following poll is a vibe-check and not binding.
|
||||
""",
|
||||
"""\
|
||||
/poll Approve beta backport of #{number}?
|
||||
/poll Should #{number} be beta backported?
|
||||
approve
|
||||
decline
|
||||
don't know
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue