Auto merge of #108677 - matthiaskrgr:rollup-i91cxuf, r=matthiaskrgr
Rollup of 8 pull requests Successful merges: - #108022 (Support allocations with non-Box<[u8]> bytes) - #108367 (Re-apply "switch to the macos-12-xl builder") - #108557 (Point error span at Some constructor argument when trait resolution fails) - #108573 (Explain compile-time vs run-time difference in env!() error message) - #108584 (Put backtick content from rustdoc search errors into a `<code>` elements) - #108624 (Make `ExprKind` the first field in `thir::Expr`) - #108644 (Allow setting hashmap toml values in `./configure`) - #108672 (Feed queries on impl side for RPITITs when using lower_impl_trait_in_trait_to_assoc_ty) Failed merges: r? `@ghost` `@rustbot` modify labels: rollup
This commit is contained in:
commit
7a809ce899
12
.github/workflows/ci.yml
vendored
12
.github/workflows/ci.yml
vendored
@ -322,7 +322,7 @@ jobs:
|
||||
NO_DEBUG_ASSERTIONS: 1
|
||||
NO_OVERFLOW_CHECKS: 1
|
||||
DIST_REQUIRE_ALL_TOOLS: 1
|
||||
os: macos-latest
|
||||
os: macos-12-xl
|
||||
- name: dist-apple-various
|
||||
env:
|
||||
SCRIPT: "./x.py dist bootstrap --include-default-paths --host='' --target=aarch64-apple-ios,x86_64-apple-ios,aarch64-apple-ios-sim"
|
||||
@ -333,7 +333,7 @@ jobs:
|
||||
NO_LLVM_ASSERTIONS: 1
|
||||
NO_DEBUG_ASSERTIONS: 1
|
||||
NO_OVERFLOW_CHECKS: 1
|
||||
os: macos-latest
|
||||
os: macos-12-xl
|
||||
- name: dist-x86_64-apple-alt
|
||||
env:
|
||||
SCRIPT: "./x.py dist bootstrap --include-default-paths"
|
||||
@ -344,7 +344,7 @@ jobs:
|
||||
NO_LLVM_ASSERTIONS: 1
|
||||
NO_DEBUG_ASSERTIONS: 1
|
||||
NO_OVERFLOW_CHECKS: 1
|
||||
os: macos-latest
|
||||
os: macos-12-xl
|
||||
- name: x86_64-apple-1
|
||||
env:
|
||||
SCRIPT: "./x.py --stage 2 test --exclude tests/ui --exclude tests/rustdoc --exclude tests/run-make-fulldeps"
|
||||
@ -355,7 +355,7 @@ jobs:
|
||||
NO_LLVM_ASSERTIONS: 1
|
||||
NO_DEBUG_ASSERTIONS: 1
|
||||
NO_OVERFLOW_CHECKS: 1
|
||||
os: macos-latest
|
||||
os: macos-12-xl
|
||||
- name: x86_64-apple-2
|
||||
env:
|
||||
SCRIPT: "./x.py --stage 2 test tests/ui tests/rustdoc tests/run-make-fulldeps"
|
||||
@ -366,7 +366,7 @@ jobs:
|
||||
NO_LLVM_ASSERTIONS: 1
|
||||
NO_DEBUG_ASSERTIONS: 1
|
||||
NO_OVERFLOW_CHECKS: 1
|
||||
os: macos-latest
|
||||
os: macos-12-xl
|
||||
- name: dist-aarch64-apple
|
||||
env:
|
||||
SCRIPT: "./x.py dist bootstrap --include-default-paths --stage 2"
|
||||
@ -381,7 +381,7 @@ jobs:
|
||||
NO_OVERFLOW_CHECKS: 1
|
||||
DIST_REQUIRE_ALL_TOOLS: 1
|
||||
JEMALLOC_SYS_WITH_LG_PAGE: 14
|
||||
os: macos-latest
|
||||
os: macos-12-xl
|
||||
- name: x86_64-msvc-1
|
||||
env:
|
||||
RUST_CONFIGURE_ARGS: "--build=x86_64-pc-windows-msvc --enable-profiler"
|
||||
|
@ -53,7 +53,7 @@ pub fn expand_env<'cx>(
|
||||
tts: TokenStream,
|
||||
) -> Box<dyn base::MacResult + 'cx> {
|
||||
let mut exprs = match get_exprs_from_tts(cx, tts) {
|
||||
Some(exprs) if exprs.is_empty() => {
|
||||
Some(exprs) if exprs.is_empty() || exprs.len() > 2 => {
|
||||
cx.span_err(sp, "env! takes 1 or 2 arguments");
|
||||
return DummyResult::any(sp);
|
||||
}
|
||||
@ -64,28 +64,48 @@ pub fn expand_env<'cx>(
|
||||
let Some((var, _style)) = expr_to_string(cx, exprs.next().unwrap(), "expected string literal") else {
|
||||
return DummyResult::any(sp);
|
||||
};
|
||||
let msg = match exprs.next() {
|
||||
None => Symbol::intern(&format!("environment variable `{}` not defined", var)),
|
||||
|
||||
let custom_msg = match exprs.next() {
|
||||
None => None,
|
||||
Some(second) => match expr_to_string(cx, second, "expected string literal") {
|
||||
None => return DummyResult::any(sp),
|
||||
Some((s, _style)) => s,
|
||||
Some((s, _style)) => Some(s),
|
||||
},
|
||||
};
|
||||
|
||||
if exprs.next().is_some() {
|
||||
cx.span_err(sp, "env! takes 1 or 2 arguments");
|
||||
return DummyResult::any(sp);
|
||||
}
|
||||
|
||||
let sp = cx.with_def_site_ctxt(sp);
|
||||
let value = env::var(var.as_str()).ok().as_deref().map(Symbol::intern);
|
||||
cx.sess.parse_sess.env_depinfo.borrow_mut().insert((var, value));
|
||||
let e = match value {
|
||||
None => {
|
||||
cx.span_err(sp, msg.as_str());
|
||||
let (msg, help) = match custom_msg {
|
||||
None => (
|
||||
format!("environment variable `{var}` not defined at compile time"),
|
||||
Some(help_for_missing_env_var(var.as_str())),
|
||||
),
|
||||
Some(s) => (s.to_string(), None),
|
||||
};
|
||||
let mut diag = cx.struct_span_err(sp, &msg);
|
||||
if let Some(help) = help {
|
||||
diag.help(help);
|
||||
}
|
||||
diag.emit();
|
||||
return DummyResult::any(sp);
|
||||
}
|
||||
Some(value) => cx.expr_str(sp, value),
|
||||
};
|
||||
MacEager::expr(e)
|
||||
}
|
||||
|
||||
fn help_for_missing_env_var(var: &str) -> String {
|
||||
if var.starts_with("CARGO_")
|
||||
|| var.starts_with("DEP_")
|
||||
|| matches!(var, "OUT_DIR" | "OPT_LEVEL" | "PROFILE" | "HOST" | "TARGET")
|
||||
{
|
||||
format!(
|
||||
"Cargo sets build script variables at run time. Use `std::env::var(\"{var}\")` instead"
|
||||
)
|
||||
} else {
|
||||
format!("Use `std::env::var(\"{var}\")` to read the variable at run time")
|
||||
}
|
||||
}
|
||||
|
@ -16,8 +16,8 @@
|
||||
use crate::const_eval::CheckAlignment;
|
||||
|
||||
use super::{
|
||||
AllocId, AllocRange, Allocation, ConstAllocation, Frame, ImmTy, InterpCx, InterpResult,
|
||||
MemoryKind, OpTy, Operand, PlaceTy, Pointer, Provenance, Scalar, StackPopUnwind,
|
||||
AllocBytes, AllocId, AllocRange, Allocation, ConstAllocation, Frame, ImmTy, InterpCx,
|
||||
InterpResult, MemoryKind, OpTy, Operand, PlaceTy, Pointer, Provenance, Scalar, StackPopUnwind,
|
||||
};
|
||||
|
||||
/// Data returned by Machine::stack_pop,
|
||||
@ -105,10 +105,16 @@ pub trait Machine<'mir, 'tcx>: Sized {
|
||||
/// Extra data stored in every allocation.
|
||||
type AllocExtra: Debug + Clone + 'static;
|
||||
|
||||
/// Type for the bytes of the allocation.
|
||||
type Bytes: AllocBytes + 'static;
|
||||
|
||||
/// Memory's allocation map
|
||||
type MemoryMap: AllocMap<
|
||||
AllocId,
|
||||
(MemoryKind<Self::MemoryKind>, Allocation<Self::Provenance, Self::AllocExtra>),
|
||||
(
|
||||
MemoryKind<Self::MemoryKind>,
|
||||
Allocation<Self::Provenance, Self::AllocExtra, Self::Bytes>,
|
||||
),
|
||||
> + Default
|
||||
+ Clone;
|
||||
|
||||
@ -338,7 +344,7 @@ fn adjust_allocation<'b>(
|
||||
id: AllocId,
|
||||
alloc: Cow<'b, Allocation>,
|
||||
kind: Option<MemoryKind<Self::MemoryKind>>,
|
||||
) -> InterpResult<'tcx, Cow<'b, Allocation<Self::Provenance, Self::AllocExtra>>>;
|
||||
) -> InterpResult<'tcx, Cow<'b, Allocation<Self::Provenance, Self::AllocExtra, Self::Bytes>>>;
|
||||
|
||||
fn eval_inline_asm(
|
||||
_ecx: &mut InterpCx<'mir, 'tcx, Self>,
|
||||
@ -459,6 +465,7 @@ fn after_stack_pop(
|
||||
|
||||
type AllocExtra = ();
|
||||
type FrameExtra = ();
|
||||
type Bytes = Box<[u8]>;
|
||||
|
||||
#[inline(always)]
|
||||
fn use_addr_for_alignment_check(_ecx: &InterpCx<$mir, $tcx, Self>) -> bool {
|
||||
|
@ -21,8 +21,9 @@
|
||||
use crate::const_eval::CheckAlignment;
|
||||
|
||||
use super::{
|
||||
alloc_range, AllocId, AllocMap, AllocRange, Allocation, CheckInAllocMsg, GlobalAlloc, InterpCx,
|
||||
InterpResult, Machine, MayLeak, Pointer, PointerArithmetic, Provenance, Scalar,
|
||||
alloc_range, AllocBytes, AllocId, AllocMap, AllocRange, Allocation, CheckInAllocMsg,
|
||||
GlobalAlloc, InterpCx, InterpResult, Machine, MayLeak, Pointer, PointerArithmetic, Provenance,
|
||||
Scalar,
|
||||
};
|
||||
|
||||
#[derive(Debug, PartialEq, Copy, Clone)]
|
||||
@ -114,16 +115,16 @@ pub struct Memory<'mir, 'tcx, M: Machine<'mir, 'tcx>> {
|
||||
/// A reference to some allocation that was already bounds-checked for the given region
|
||||
/// and had the on-access machine hooks run.
|
||||
#[derive(Copy, Clone)]
|
||||
pub struct AllocRef<'a, 'tcx, Prov: Provenance, Extra> {
|
||||
alloc: &'a Allocation<Prov, Extra>,
|
||||
pub struct AllocRef<'a, 'tcx, Prov: Provenance, Extra, Bytes: AllocBytes = Box<[u8]>> {
|
||||
alloc: &'a Allocation<Prov, Extra, Bytes>,
|
||||
range: AllocRange,
|
||||
tcx: TyCtxt<'tcx>,
|
||||
alloc_id: AllocId,
|
||||
}
|
||||
/// A reference to some allocation that was already bounds-checked for the given region
|
||||
/// and had the on-access machine hooks run.
|
||||
pub struct AllocRefMut<'a, 'tcx, Prov: Provenance, Extra> {
|
||||
alloc: &'a mut Allocation<Prov, Extra>,
|
||||
pub struct AllocRefMut<'a, 'tcx, Prov: Provenance, Extra, Bytes: AllocBytes = Box<[u8]>> {
|
||||
alloc: &'a mut Allocation<Prov, Extra, Bytes>,
|
||||
range: AllocRange,
|
||||
tcx: TyCtxt<'tcx>,
|
||||
alloc_id: AllocId,
|
||||
@ -483,7 +484,7 @@ fn get_global_alloc(
|
||||
&self,
|
||||
id: AllocId,
|
||||
is_write: bool,
|
||||
) -> InterpResult<'tcx, Cow<'tcx, Allocation<M::Provenance, M::AllocExtra>>> {
|
||||
) -> InterpResult<'tcx, Cow<'tcx, Allocation<M::Provenance, M::AllocExtra, M::Bytes>>> {
|
||||
let (alloc, def_id) = match self.tcx.try_get_global_alloc(id) {
|
||||
Some(GlobalAlloc::Memory(mem)) => {
|
||||
// Memory of a constant or promoted or anonymous memory referenced by a static.
|
||||
@ -526,6 +527,17 @@ fn get_global_alloc(
|
||||
)
|
||||
}
|
||||
|
||||
/// Get the base address for the bytes in an `Allocation` specified by the
|
||||
/// `AllocID` passed in; error if no such allocation exists.
|
||||
///
|
||||
/// It is up to the caller to take sufficient care when using this address:
|
||||
/// there could be provenance or uninit memory in there, and other memory
|
||||
/// accesses could invalidate the exposed pointer.
|
||||
pub fn alloc_base_addr(&self, id: AllocId) -> InterpResult<'tcx, *const u8> {
|
||||
let alloc = self.get_alloc_raw(id)?;
|
||||
Ok(alloc.base_addr())
|
||||
}
|
||||
|
||||
/// Gives raw access to the `Allocation`, without bounds or alignment checks.
|
||||
/// The caller is responsible for calling the access hooks!
|
||||
///
|
||||
@ -533,7 +545,7 @@ fn get_global_alloc(
|
||||
fn get_alloc_raw(
|
||||
&self,
|
||||
id: AllocId,
|
||||
) -> InterpResult<'tcx, &Allocation<M::Provenance, M::AllocExtra>> {
|
||||
) -> InterpResult<'tcx, &Allocation<M::Provenance, M::AllocExtra, M::Bytes>> {
|
||||
// The error type of the inner closure here is somewhat funny. We have two
|
||||
// ways of "erroring": An actual error, or because we got a reference from
|
||||
// `get_global_alloc` that we can actually use directly without inserting anything anywhere.
|
||||
@ -569,7 +581,8 @@ pub fn get_ptr_alloc<'a>(
|
||||
ptr: Pointer<Option<M::Provenance>>,
|
||||
size: Size,
|
||||
align: Align,
|
||||
) -> InterpResult<'tcx, Option<AllocRef<'a, 'tcx, M::Provenance, M::AllocExtra>>> {
|
||||
) -> InterpResult<'tcx, Option<AllocRef<'a, 'tcx, M::Provenance, M::AllocExtra, M::Bytes>>>
|
||||
{
|
||||
let ptr_and_alloc = self.check_and_deref_ptr(
|
||||
ptr,
|
||||
size,
|
||||
@ -612,7 +625,7 @@ pub fn get_alloc_mutability<'a>(&'a self, id: AllocId) -> InterpResult<'tcx, Mut
|
||||
fn get_alloc_raw_mut(
|
||||
&mut self,
|
||||
id: AllocId,
|
||||
) -> InterpResult<'tcx, (&mut Allocation<M::Provenance, M::AllocExtra>, &mut M)> {
|
||||
) -> InterpResult<'tcx, (&mut Allocation<M::Provenance, M::AllocExtra, M::Bytes>, &mut M)> {
|
||||
// We have "NLL problem case #3" here, which cannot be worked around without loss of
|
||||
// efficiency even for the common case where the key is in the map.
|
||||
// <https://rust-lang.github.io/rfcs/2094-nll.html#problem-case-3-conditional-control-flow-across-functions>
|
||||
@ -641,7 +654,8 @@ pub fn get_ptr_alloc_mut<'a>(
|
||||
ptr: Pointer<Option<M::Provenance>>,
|
||||
size: Size,
|
||||
align: Align,
|
||||
) -> InterpResult<'tcx, Option<AllocRefMut<'a, 'tcx, M::Provenance, M::AllocExtra>>> {
|
||||
) -> InterpResult<'tcx, Option<AllocRefMut<'a, 'tcx, M::Provenance, M::AllocExtra, M::Bytes>>>
|
||||
{
|
||||
let parts = self.get_ptr_access(ptr, size, align)?;
|
||||
if let Some((alloc_id, offset, prov)) = parts {
|
||||
let tcx = *self.tcx;
|
||||
@ -840,11 +854,11 @@ pub struct DumpAllocs<'a, 'mir, 'tcx, M: Machine<'mir, 'tcx>> {
|
||||
impl<'a, 'mir, 'tcx, M: Machine<'mir, 'tcx>> std::fmt::Debug for DumpAllocs<'a, 'mir, 'tcx, M> {
|
||||
fn fmt(&self, fmt: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||
// Cannot be a closure because it is generic in `Prov`, `Extra`.
|
||||
fn write_allocation_track_relocs<'tcx, Prov: Provenance, Extra>(
|
||||
fn write_allocation_track_relocs<'tcx, Prov: Provenance, Extra, Bytes: AllocBytes>(
|
||||
fmt: &mut std::fmt::Formatter<'_>,
|
||||
tcx: TyCtxt<'tcx>,
|
||||
allocs_to_print: &mut VecDeque<AllocId>,
|
||||
alloc: &Allocation<Prov, Extra>,
|
||||
alloc: &Allocation<Prov, Extra, Bytes>,
|
||||
) -> std::fmt::Result {
|
||||
for alloc_id in alloc.provenance().provenances().filter_map(|prov| prov.get_alloc_id())
|
||||
{
|
||||
@ -912,7 +926,9 @@ fn write_allocation_track_relocs<'tcx, Prov: Provenance, Extra>(
|
||||
}
|
||||
|
||||
/// Reading and writing.
|
||||
impl<'tcx, 'a, Prov: Provenance, Extra> AllocRefMut<'a, 'tcx, Prov, Extra> {
|
||||
impl<'tcx, 'a, Prov: Provenance, Extra, Bytes: AllocBytes>
|
||||
AllocRefMut<'a, 'tcx, Prov, Extra, Bytes>
|
||||
{
|
||||
/// `range` is relative to this allocation reference, not the base of the allocation.
|
||||
pub fn write_scalar(&mut self, range: AllocRange, val: Scalar<Prov>) -> InterpResult<'tcx> {
|
||||
let range = self.range.subrange(range);
|
||||
@ -937,7 +953,7 @@ pub fn write_uninit(&mut self) -> InterpResult<'tcx> {
|
||||
}
|
||||
}
|
||||
|
||||
impl<'tcx, 'a, Prov: Provenance, Extra> AllocRef<'a, 'tcx, Prov, Extra> {
|
||||
impl<'tcx, 'a, Prov: Provenance, Extra, Bytes: AllocBytes> AllocRef<'a, 'tcx, Prov, Extra, Bytes> {
|
||||
/// `range` is relative to this allocation reference, not the base of the allocation.
|
||||
pub fn read_scalar(
|
||||
&self,
|
||||
|
@ -353,7 +353,8 @@ pub fn deref_operand(
|
||||
pub(super) fn get_place_alloc(
|
||||
&self,
|
||||
place: &MPlaceTy<'tcx, M::Provenance>,
|
||||
) -> InterpResult<'tcx, Option<AllocRef<'_, 'tcx, M::Provenance, M::AllocExtra>>> {
|
||||
) -> InterpResult<'tcx, Option<AllocRef<'_, 'tcx, M::Provenance, M::AllocExtra, M::Bytes>>>
|
||||
{
|
||||
assert!(place.layout.is_sized());
|
||||
assert!(!place.meta.has_meta());
|
||||
let size = place.layout.size;
|
||||
@ -364,7 +365,8 @@ pub(super) fn get_place_alloc(
|
||||
pub(super) fn get_place_alloc_mut(
|
||||
&mut self,
|
||||
place: &MPlaceTy<'tcx, M::Provenance>,
|
||||
) -> InterpResult<'tcx, Option<AllocRefMut<'_, 'tcx, M::Provenance, M::AllocExtra>>> {
|
||||
) -> InterpResult<'tcx, Option<AllocRefMut<'_, 'tcx, M::Provenance, M::AllocExtra, M::Bytes>>>
|
||||
{
|
||||
assert!(place.layout.is_sized());
|
||||
assert!(!place.meta.has_meta());
|
||||
let size = place.layout.size;
|
||||
|
@ -714,12 +714,26 @@ fn blame_specific_part_of_expr_corresponding_to_generic_param(
|
||||
self.tcx.parent(expr_ctor_def_id)
|
||||
}
|
||||
hir::def::DefKind::Ctor(hir::def::CtorOf::Variant, hir::def::CtorKind::Fn) => {
|
||||
// If this is a variant, its parent is the type definition.
|
||||
if in_ty_adt.did() != self.tcx.parent(expr_ctor_def_id) {
|
||||
// For a typical enum like
|
||||
// `enum Blah<T> { Variant(T) }`
|
||||
// we get the following resolutions:
|
||||
// - expr_ctor_def_id ::: DefId(0:29 ~ source_file[b442]::Blah::Variant::{constructor#0})
|
||||
// - self.tcx.parent(expr_ctor_def_id) ::: DefId(0:28 ~ source_file[b442]::Blah::Variant)
|
||||
// - self.tcx.parent(self.tcx.parent(expr_ctor_def_id)) ::: DefId(0:26 ~ source_file[b442]::Blah)
|
||||
|
||||
// Therefore, we need to go up once to obtain the variant and up twice to obtain the type.
|
||||
// Note that this pattern still holds even when we `use` a variant or `use` an enum type to rename it, or chain `use` expressions
|
||||
// together; this resolution is handled automatically by `qpath_res`.
|
||||
|
||||
// FIXME: Deal with type aliases?
|
||||
if in_ty_adt.did() == self.tcx.parent(self.tcx.parent(expr_ctor_def_id)) {
|
||||
// The constructor definition refers to the "constructor" of the variant:
|
||||
// For example, `Some(5)` triggers this case.
|
||||
self.tcx.parent(expr_ctor_def_id)
|
||||
} else {
|
||||
// FIXME: Deal with type aliases?
|
||||
return Err(expr);
|
||||
}
|
||||
expr_ctor_def_id
|
||||
}
|
||||
_ => {
|
||||
return Err(expr);
|
||||
|
@ -8,7 +8,8 @@
|
||||
use std::borrow::Cow;
|
||||
use std::fmt;
|
||||
use std::hash;
|
||||
use std::ops::Range;
|
||||
use std::hash::Hash;
|
||||
use std::ops::{Deref, DerefMut, Range};
|
||||
use std::ptr;
|
||||
|
||||
use either::{Left, Right};
|
||||
@ -29,6 +30,39 @@
|
||||
|
||||
pub use init_mask::{InitChunk, InitChunkIter};
|
||||
|
||||
/// Functionality required for the bytes of an `Allocation`.
|
||||
pub trait AllocBytes:
|
||||
Clone + fmt::Debug + Eq + PartialEq + Hash + Deref<Target = [u8]> + DerefMut<Target = [u8]>
|
||||
{
|
||||
/// Adjust the bytes to the specified alignment -- by default, this is a no-op.
|
||||
fn adjust_to_align(self, _align: Align) -> Self;
|
||||
|
||||
/// Create an `AllocBytes` from a slice of `u8`.
|
||||
fn from_bytes<'a>(slice: impl Into<Cow<'a, [u8]>>, _align: Align) -> Self;
|
||||
|
||||
/// Create a zeroed `AllocBytes` of the specified size and alignment;
|
||||
/// call the callback error handler if there is an error in allocating the memory.
|
||||
fn zeroed(size: Size, _align: Align) -> Option<Self>;
|
||||
}
|
||||
|
||||
// Default `bytes` for `Allocation` is a `Box<[u8]>`.
|
||||
impl AllocBytes for Box<[u8]> {
|
||||
fn adjust_to_align(self, _align: Align) -> Self {
|
||||
self
|
||||
}
|
||||
|
||||
fn from_bytes<'a>(slice: impl Into<Cow<'a, [u8]>>, _align: Align) -> Self {
|
||||
Box::<[u8]>::from(slice.into())
|
||||
}
|
||||
|
||||
fn zeroed(size: Size, _align: Align) -> Option<Self> {
|
||||
let bytes = Box::<[u8]>::try_new_zeroed_slice(size.bytes_usize()).ok()?;
|
||||
// SAFETY: the box was zero-allocated, which is a valid initial value for Box<[u8]>
|
||||
let bytes = unsafe { bytes.assume_init() };
|
||||
Some(bytes)
|
||||
}
|
||||
}
|
||||
|
||||
/// This type represents an Allocation in the Miri/CTFE core engine.
|
||||
///
|
||||
/// Its public API is rather low-level, working directly with allocation offsets and a custom error
|
||||
@ -38,10 +72,10 @@
|
||||
// hashed. (see the `Hash` impl below for more details), so the impl is not derived.
|
||||
#[derive(Clone, Eq, PartialEq, TyEncodable, TyDecodable)]
|
||||
#[derive(HashStable)]
|
||||
pub struct Allocation<Prov: Provenance = AllocId, Extra = ()> {
|
||||
pub struct Allocation<Prov: Provenance = AllocId, Extra = (), Bytes = Box<[u8]>> {
|
||||
/// The actual bytes of the allocation.
|
||||
/// Note that the bytes of a pointer represent the offset of the pointer.
|
||||
bytes: Box<[u8]>,
|
||||
bytes: Bytes,
|
||||
/// Maps from byte addresses to extra provenance data for each pointer.
|
||||
/// Only the first byte of a pointer is inserted into the map; i.e.,
|
||||
/// every entry in this map applies to `pointer_size` consecutive bytes starting
|
||||
@ -220,14 +254,27 @@ pub fn subrange(self, subrange: AllocRange) -> AllocRange {
|
||||
}
|
||||
|
||||
// The constructors are all without extra; the extra gets added by a machine hook later.
|
||||
impl<Prov: Provenance> Allocation<Prov> {
|
||||
impl<Prov: Provenance, Bytes: AllocBytes> Allocation<Prov, (), Bytes> {
|
||||
/// Creates an allocation from an existing `Bytes` value - this is needed for miri FFI support
|
||||
pub fn from_raw_bytes(bytes: Bytes, align: Align, mutability: Mutability) -> Self {
|
||||
let size = Size::from_bytes(bytes.len());
|
||||
Self {
|
||||
bytes,
|
||||
provenance: ProvenanceMap::new(),
|
||||
init_mask: InitMask::new(size, true),
|
||||
align,
|
||||
mutability,
|
||||
extra: (),
|
||||
}
|
||||
}
|
||||
|
||||
/// Creates an allocation initialized by the given bytes
|
||||
pub fn from_bytes<'a>(
|
||||
slice: impl Into<Cow<'a, [u8]>>,
|
||||
align: Align,
|
||||
mutability: Mutability,
|
||||
) -> Self {
|
||||
let bytes = Box::<[u8]>::from(slice.into());
|
||||
let bytes = Bytes::from_bytes(slice, align);
|
||||
let size = Size::from_bytes(bytes.len());
|
||||
Self {
|
||||
bytes,
|
||||
@ -248,7 +295,7 @@ pub fn from_bytes_byte_aligned_immutable<'a>(slice: impl Into<Cow<'a, [u8]>>) ->
|
||||
///
|
||||
/// If `panic_on_fail` is true, this will never return `Err`.
|
||||
pub fn uninit<'tcx>(size: Size, align: Align, panic_on_fail: bool) -> InterpResult<'tcx, Self> {
|
||||
let bytes = Box::<[u8]>::try_new_zeroed_slice(size.bytes_usize()).map_err(|_| {
|
||||
let bytes = Bytes::zeroed(size, align).ok_or_else(|| {
|
||||
// This results in an error that can happen non-deterministically, since the memory
|
||||
// available to the compiler can change between runs. Normally queries are always
|
||||
// deterministic. However, we can be non-deterministic here because all uses of const
|
||||
@ -262,8 +309,7 @@ pub fn uninit<'tcx>(size: Size, align: Align, panic_on_fail: bool) -> InterpResu
|
||||
});
|
||||
InterpError::ResourceExhaustion(ResourceExhaustionInfo::MemoryExhausted)
|
||||
})?;
|
||||
// SAFETY: the box was zero-allocated, which is a valid initial value for Box<[u8]>
|
||||
let bytes = unsafe { bytes.assume_init() };
|
||||
|
||||
Ok(Allocation {
|
||||
bytes,
|
||||
provenance: ProvenanceMap::new(),
|
||||
@ -275,7 +321,7 @@ pub fn uninit<'tcx>(size: Size, align: Align, panic_on_fail: bool) -> InterpResu
|
||||
}
|
||||
}
|
||||
|
||||
impl Allocation {
|
||||
impl<Bytes: AllocBytes> Allocation<AllocId, (), Bytes> {
|
||||
/// Adjust allocation from the ones in tcx to a custom Machine instance
|
||||
/// with a different Provenance and Extra type.
|
||||
pub fn adjust_from_tcx<Prov: Provenance, Extra, Err>(
|
||||
@ -283,9 +329,11 @@ pub fn adjust_from_tcx<Prov: Provenance, Extra, Err>(
|
||||
cx: &impl HasDataLayout,
|
||||
extra: Extra,
|
||||
mut adjust_ptr: impl FnMut(Pointer<AllocId>) -> Result<Pointer<Prov>, Err>,
|
||||
) -> Result<Allocation<Prov, Extra>, Err> {
|
||||
// Compute new pointer provenance, which also adjusts the bytes.
|
||||
let mut bytes = self.bytes;
|
||||
) -> Result<Allocation<Prov, Extra, Bytes>, Err> {
|
||||
// Compute new pointer provenance, which also adjusts the bytes, and realign the pointer if
|
||||
// necessary.
|
||||
let mut bytes = self.bytes.adjust_to_align(self.align);
|
||||
|
||||
let mut new_provenance = Vec::with_capacity(self.provenance.ptrs().len());
|
||||
let ptr_size = cx.data_layout().pointer_size.bytes_usize();
|
||||
let endian = cx.data_layout().endian;
|
||||
@ -311,7 +359,7 @@ pub fn adjust_from_tcx<Prov: Provenance, Extra, Err>(
|
||||
}
|
||||
|
||||
/// Raw accessors. Provide access to otherwise private bytes.
|
||||
impl<Prov: Provenance, Extra> Allocation<Prov, Extra> {
|
||||
impl<Prov: Provenance, Extra, Bytes: AllocBytes> Allocation<Prov, Extra, Bytes> {
|
||||
pub fn len(&self) -> usize {
|
||||
self.bytes.len()
|
||||
}
|
||||
@ -340,7 +388,11 @@ pub fn provenance(&self) -> &ProvenanceMap<Prov> {
|
||||
}
|
||||
|
||||
/// Byte accessors.
|
||||
impl<Prov: Provenance, Extra> Allocation<Prov, Extra> {
|
||||
impl<Prov: Provenance, Extra, Bytes: AllocBytes> Allocation<Prov, Extra, Bytes> {
|
||||
pub fn base_addr(&self) -> *const u8 {
|
||||
self.bytes.as_ptr()
|
||||
}
|
||||
|
||||
/// This is the entirely abstraction-violating way to just grab the raw bytes without
|
||||
/// caring about provenance or initialization.
|
||||
///
|
||||
@ -412,7 +464,7 @@ pub fn get_bytes_mut_ptr(
|
||||
}
|
||||
|
||||
/// Reading and writing.
|
||||
impl<Prov: Provenance, Extra> Allocation<Prov, Extra> {
|
||||
impl<Prov: Provenance, Extra, Bytes: AllocBytes> Allocation<Prov, Extra, Bytes> {
|
||||
/// Sets the init bit for the given range.
|
||||
fn mark_init(&mut self, range: AllocRange, is_init: bool) {
|
||||
if range.size.bytes() == 0 {
|
||||
|
@ -127,8 +127,8 @@ macro_rules! throw_machine_stop {
|
||||
pub use self::value::{get_slice_bytes, ConstAlloc, ConstValue, Scalar};
|
||||
|
||||
pub use self::allocation::{
|
||||
alloc_range, AllocError, AllocRange, AllocResult, Allocation, ConstAllocation, InitChunk,
|
||||
InitChunkIter,
|
||||
alloc_range, AllocBytes, AllocError, AllocRange, AllocResult, Allocation, ConstAllocation,
|
||||
InitChunk, InitChunkIter,
|
||||
};
|
||||
|
||||
pub use self::pointer::{Pointer, PointerArithmetic, Provenance};
|
||||
|
@ -12,8 +12,8 @@
|
||||
use rustc_hir::def_id::DefId;
|
||||
use rustc_index::vec::Idx;
|
||||
use rustc_middle::mir::interpret::{
|
||||
alloc_range, read_target_uint, AllocId, Allocation, ConstAllocation, ConstValue, GlobalAlloc,
|
||||
Pointer, Provenance,
|
||||
alloc_range, read_target_uint, AllocBytes, AllocId, Allocation, ConstAllocation, ConstValue,
|
||||
GlobalAlloc, Pointer, Provenance,
|
||||
};
|
||||
use rustc_middle::mir::visit::Visitor;
|
||||
use rustc_middle::mir::*;
|
||||
@ -787,21 +787,21 @@ fn visit_constant(&mut self, c: &Constant<'tcx>, _: Location) {
|
||||
/// After the hex dump, an ascii dump follows, replacing all unprintable characters (control
|
||||
/// characters or characters whose value is larger than 127) with a `.`
|
||||
/// This also prints provenance adequately.
|
||||
pub fn display_allocation<'a, 'tcx, Prov: Provenance, Extra>(
|
||||
pub fn display_allocation<'a, 'tcx, Prov: Provenance, Extra, Bytes: AllocBytes>(
|
||||
tcx: TyCtxt<'tcx>,
|
||||
alloc: &'a Allocation<Prov, Extra>,
|
||||
) -> RenderAllocation<'a, 'tcx, Prov, Extra> {
|
||||
alloc: &'a Allocation<Prov, Extra, Bytes>,
|
||||
) -> RenderAllocation<'a, 'tcx, Prov, Extra, Bytes> {
|
||||
RenderAllocation { tcx, alloc }
|
||||
}
|
||||
|
||||
#[doc(hidden)]
|
||||
pub struct RenderAllocation<'a, 'tcx, Prov: Provenance, Extra> {
|
||||
pub struct RenderAllocation<'a, 'tcx, Prov: Provenance, Extra, Bytes: AllocBytes> {
|
||||
tcx: TyCtxt<'tcx>,
|
||||
alloc: &'a Allocation<Prov, Extra>,
|
||||
alloc: &'a Allocation<Prov, Extra, Bytes>,
|
||||
}
|
||||
|
||||
impl<'a, 'tcx, Prov: Provenance, Extra> std::fmt::Display
|
||||
for RenderAllocation<'a, 'tcx, Prov, Extra>
|
||||
impl<'a, 'tcx, Prov: Provenance, Extra, Bytes: AllocBytes> std::fmt::Display
|
||||
for RenderAllocation<'a, 'tcx, Prov, Extra, Bytes>
|
||||
{
|
||||
fn fmt(&self, w: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||
let RenderAllocation { tcx, alloc } = *self;
|
||||
@ -845,9 +845,9 @@ fn write_allocation_newline(
|
||||
/// The `prefix` argument allows callers to add an arbitrary prefix before each line (even if there
|
||||
/// is only one line). Note that your prefix should contain a trailing space as the lines are
|
||||
/// printed directly after it.
|
||||
fn write_allocation_bytes<'tcx, Prov: Provenance, Extra>(
|
||||
fn write_allocation_bytes<'tcx, Prov: Provenance, Extra, Bytes: AllocBytes>(
|
||||
tcx: TyCtxt<'tcx>,
|
||||
alloc: &Allocation<Prov, Extra>,
|
||||
alloc: &Allocation<Prov, Extra, Bytes>,
|
||||
w: &mut dyn std::fmt::Write,
|
||||
prefix: &str,
|
||||
) -> std::fmt::Result {
|
||||
|
@ -237,6 +237,9 @@ pub enum StmtKind<'tcx> {
|
||||
/// A THIR expression.
|
||||
#[derive(Clone, Debug, HashStable)]
|
||||
pub struct Expr<'tcx> {
|
||||
/// kind of expression
|
||||
pub kind: ExprKind<'tcx>,
|
||||
|
||||
/// The type of this expression
|
||||
pub ty: Ty<'tcx>,
|
||||
|
||||
@ -246,9 +249,6 @@ pub struct Expr<'tcx> {
|
||||
|
||||
/// span of the expression in the source
|
||||
pub span: Span,
|
||||
|
||||
/// kind of expression
|
||||
pub kind: ExprKind<'tcx>,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, HashStable)]
|
||||
|
@ -53,9 +53,37 @@ fn associated_item_def_ids(tcx: TyCtxt<'_>, def_id: DefId) -> &[DefId] {
|
||||
)
|
||||
}
|
||||
}
|
||||
hir::ItemKind::Impl(ref impl_) => tcx.arena.alloc_from_iter(
|
||||
impl_.items.iter().map(|impl_item_ref| impl_item_ref.id.owner_id.to_def_id()),
|
||||
),
|
||||
hir::ItemKind::Impl(ref impl_) => {
|
||||
if tcx.sess.opts.unstable_opts.lower_impl_trait_in_trait_to_assoc_ty {
|
||||
// We collect RPITITs for each trait method's return type, on the impl side too and
|
||||
// create a corresponding associated item using
|
||||
// associated_items_for_impl_trait_in_trait query.
|
||||
tcx.arena.alloc_from_iter(
|
||||
impl_
|
||||
.items
|
||||
.iter()
|
||||
.map(|impl_item_ref| impl_item_ref.id.owner_id.to_def_id())
|
||||
.chain(impl_.of_trait.iter().flat_map(|_| {
|
||||
impl_
|
||||
.items
|
||||
.iter()
|
||||
.filter(|impl_item_ref| {
|
||||
matches!(impl_item_ref.kind, hir::AssocItemKind::Fn { .. })
|
||||
})
|
||||
.flat_map(|impl_item_ref| {
|
||||
let impl_fn_def_id =
|
||||
impl_item_ref.id.owner_id.def_id.to_def_id();
|
||||
tcx.associated_items_for_impl_trait_in_trait(impl_fn_def_id)
|
||||
})
|
||||
.map(|def_id| *def_id)
|
||||
})),
|
||||
)
|
||||
} else {
|
||||
tcx.arena.alloc_from_iter(
|
||||
impl_.items.iter().map(|impl_item_ref| impl_item_ref.id.owner_id.to_def_id()),
|
||||
)
|
||||
}
|
||||
}
|
||||
_ => span_bug!(item.span, "associated_item_def_ids: not impl or trait"),
|
||||
}
|
||||
}
|
||||
@ -290,8 +318,40 @@ fn impl_associated_item_for_impl_trait_in_trait(
|
||||
) -> LocalDefId {
|
||||
let impl_def_id = tcx.local_parent(impl_fn_def_id);
|
||||
|
||||
let span = tcx.def_span(trait_assoc_def_id);
|
||||
// FIXME fix the span, we probably want the def_id of the return type of the function
|
||||
let span = tcx.def_span(impl_fn_def_id);
|
||||
let impl_assoc_ty = tcx.at(span).create_def(impl_def_id, DefPathData::ImplTraitAssocTy);
|
||||
|
||||
impl_assoc_ty.def_id()
|
||||
let local_def_id = impl_assoc_ty.def_id();
|
||||
let def_id = local_def_id.to_def_id();
|
||||
|
||||
impl_assoc_ty.opt_def_kind(Some(DefKind::AssocTy));
|
||||
|
||||
// There's no HIR associated with this new synthesized `def_id`, so feed
|
||||
// `opt_local_def_id_to_hir_id` with `None`.
|
||||
impl_assoc_ty.opt_local_def_id_to_hir_id(None);
|
||||
|
||||
// Add the def_id of the function that generated this synthesized associated type.
|
||||
impl_assoc_ty.opt_rpitit_info(Some(ImplTraitInTraitData::Impl {
|
||||
fn_def_id: impl_fn_def_id.to_def_id(),
|
||||
}));
|
||||
|
||||
impl_assoc_ty.associated_item(ty::AssocItem {
|
||||
name: kw::Empty,
|
||||
kind: ty::AssocKind::Type,
|
||||
def_id,
|
||||
trait_item_def_id: Some(trait_assoc_def_id.to_def_id()),
|
||||
container: ty::ImplContainer,
|
||||
fn_has_self_parameter: false,
|
||||
});
|
||||
|
||||
// Copy impl_defaultness of the containing function.
|
||||
impl_assoc_ty.impl_defaultness(tcx.impl_defaultness(impl_fn_def_id));
|
||||
|
||||
// Copy generics_of the trait's associated item.
|
||||
// FIXME: This is not correct, in particular the parent is going to be wrong. So we would need
|
||||
// to copy from trait_assoc_def_id and adjust things.
|
||||
impl_assoc_ty.generics_of(tcx.generics_of(trait_assoc_def_id).clone());
|
||||
|
||||
local_def_id
|
||||
}
|
||||
|
@ -442,6 +442,8 @@ def to_toml(value):
|
||||
return value
|
||||
else:
|
||||
return "'" + value + "'"
|
||||
elif isinstance(value, dict):
|
||||
return "{" + ", ".join(map(lambda a: "{} = {}".format(to_toml(a[0]), to_toml(a[1])), value.items())) + "}"
|
||||
else:
|
||||
raise RuntimeError('no toml')
|
||||
|
||||
|
@ -78,7 +78,7 @@ x--expand-yaml-anchors--remove:
|
||||
<<: *base-job
|
||||
|
||||
- &job-macos-xl
|
||||
os: macos-latest # We don't have an XL builder for this
|
||||
os: macos-12-xl
|
||||
<<: *base-job
|
||||
|
||||
- &job-windows-xl
|
||||
|
@ -90,7 +90,6 @@ module.exports = {
|
||||
"no-return-assign": "error",
|
||||
"no-script-url": "error",
|
||||
"no-sequences": "error",
|
||||
"no-throw-literal": "error",
|
||||
"no-div-regex": "error",
|
||||
}
|
||||
};
|
||||
|
@ -1260,6 +1260,11 @@ a.tooltip:hover::after {
|
||||
color: var(--search-tab-title-count-color);
|
||||
}
|
||||
|
||||
#search .error code {
|
||||
border-radius: 3px;
|
||||
background-color: var(--search-error-code-background-color);
|
||||
}
|
||||
|
||||
#src-sidebar-toggle {
|
||||
position: sticky;
|
||||
top: 0;
|
||||
|
@ -43,6 +43,7 @@ Original by Dempfi (https://github.com/dempfi/ayu)
|
||||
--search-result-link-focus-background-color: #3c3c3c;
|
||||
--search-result-border-color: #aaa3;
|
||||
--search-color: #fff;
|
||||
--search-error-code-background-color: #4f4c4c;
|
||||
--search-results-alias-color: #c5c5c5;
|
||||
--search-results-grey-color: #999;
|
||||
--search-tab-title-count-color: #888;
|
||||
|
@ -38,6 +38,7 @@
|
||||
--search-result-link-focus-background-color: #616161;
|
||||
--search-result-border-color: #aaa3;
|
||||
--search-color: #111;
|
||||
--search-error-code-background-color: #484848;
|
||||
--search-results-alias-color: #fff;
|
||||
--search-results-grey-color: #ccc;
|
||||
--search-tab-title-count-color: #888;
|
||||
|
@ -38,6 +38,7 @@
|
||||
--search-result-link-focus-background-color: #ccc;
|
||||
--search-result-border-color: #aaa3;
|
||||
--search-color: #000;
|
||||
--search-error-code-background-color: #d0cccc;
|
||||
--search-results-alias-color: #000;
|
||||
--search-results-grey-color: #999;
|
||||
--search-tab-title-count-color: #888;
|
||||
|
@ -144,7 +144,7 @@ function initSearch(rawSearchIndex) {
|
||||
function itemTypeFromName(typename) {
|
||||
const index = itemTypes.findIndex(i => i === typename);
|
||||
if (index < 0) {
|
||||
throw new Error("Unknown type filter `" + typename + "`");
|
||||
throw ["Unknown type filter ", typename];
|
||||
}
|
||||
return index;
|
||||
}
|
||||
@ -164,21 +164,21 @@ function initSearch(rawSearchIndex) {
|
||||
*/
|
||||
function getStringElem(query, parserState, isInGenerics) {
|
||||
if (isInGenerics) {
|
||||
throw new Error("`\"` cannot be used in generics");
|
||||
throw ["Unexpected ", "\"", " in generics"];
|
||||
} else if (query.literalSearch) {
|
||||
throw new Error("Cannot have more than one literal search element");
|
||||
throw ["Cannot have more than one literal search element"];
|
||||
} else if (parserState.totalElems - parserState.genericsElems > 0) {
|
||||
throw new Error("Cannot use literal search when there is more than one element");
|
||||
throw ["Cannot use literal search when there is more than one element"];
|
||||
}
|
||||
parserState.pos += 1;
|
||||
const start = parserState.pos;
|
||||
const end = getIdentEndPosition(parserState);
|
||||
if (parserState.pos >= parserState.length) {
|
||||
throw new Error("Unclosed `\"`");
|
||||
throw ["Unclosed ", "\""];
|
||||
} else if (parserState.userQuery[end] !== "\"") {
|
||||
throw new Error(`Unexpected \`${parserState.userQuery[end]}\` in a string element`);
|
||||
throw ["Unexpected ", parserState.userQuery[end], " in a string element"];
|
||||
} else if (start === end) {
|
||||
throw new Error("Cannot have empty string element");
|
||||
throw ["Cannot have empty string element"];
|
||||
}
|
||||
// To skip the quote at the end.
|
||||
parserState.pos += 1;
|
||||
@ -257,7 +257,7 @@ function initSearch(rawSearchIndex) {
|
||||
return;
|
||||
}
|
||||
if (query.literalSearch && parserState.totalElems - parserState.genericsElems > 0) {
|
||||
throw new Error("You cannot have more than one element if you use quotes");
|
||||
throw ["You cannot have more than one element if you use quotes"];
|
||||
}
|
||||
const pathSegments = name.split("::");
|
||||
if (pathSegments.length > 1) {
|
||||
@ -266,17 +266,17 @@ function initSearch(rawSearchIndex) {
|
||||
|
||||
if (pathSegment.length === 0) {
|
||||
if (i === 0) {
|
||||
throw new Error("Paths cannot start with `::`");
|
||||
throw ["Paths cannot start with ", "::"];
|
||||
} else if (i + 1 === len) {
|
||||
throw new Error("Paths cannot end with `::`");
|
||||
throw ["Paths cannot end with ", "::"];
|
||||
}
|
||||
throw new Error("Unexpected `::::`");
|
||||
throw ["Unexpected ", "::::"];
|
||||
}
|
||||
}
|
||||
}
|
||||
// In case we only have something like `<p>`, there is no name.
|
||||
if (pathSegments.length === 0 || (pathSegments.length === 1 && pathSegments[0] === "")) {
|
||||
throw new Error("Found generics without a path");
|
||||
throw ["Found generics without a path"];
|
||||
}
|
||||
parserState.totalElems += 1;
|
||||
if (isInGenerics) {
|
||||
@ -308,15 +308,15 @@ function initSearch(rawSearchIndex) {
|
||||
if (!isIdentCharacter(c)) {
|
||||
if (c === "!") {
|
||||
if (foundExclamation !== -1) {
|
||||
throw new Error("Cannot have more than one `!` in an ident");
|
||||
throw ["Cannot have more than one ", "!", " in an ident"];
|
||||
} else if (parserState.pos + 1 < parserState.length &&
|
||||
isIdentCharacter(parserState.userQuery[parserState.pos + 1])
|
||||
) {
|
||||
throw new Error("`!` can only be at the end of an ident");
|
||||
throw ["Unexpected ", "!", ": it can only be at the end of an ident"];
|
||||
}
|
||||
foundExclamation = parserState.pos;
|
||||
} else if (isErrorCharacter(c)) {
|
||||
throw new Error(`Unexpected \`${c}\``);
|
||||
throw ["Unexpected ", c];
|
||||
} else if (
|
||||
isStopCharacter(c) ||
|
||||
isSpecialStartCharacter(c) ||
|
||||
@ -329,7 +329,7 @@ function initSearch(rawSearchIndex) {
|
||||
}
|
||||
if (foundExclamation !== -1) {
|
||||
if (start <= (end - 2)) {
|
||||
throw new Error("Cannot have associated items in macros");
|
||||
throw ["Cannot have associated items in macros"];
|
||||
} else {
|
||||
// if start == end - 1, we got the never type
|
||||
// while the never type has no associated macros, we still
|
||||
@ -340,7 +340,7 @@ function initSearch(rawSearchIndex) {
|
||||
// Skip current ":".
|
||||
parserState.pos += 1;
|
||||
} else {
|
||||
throw new Error(`Unexpected \`${c}\``);
|
||||
throw ["Unexpected ", c];
|
||||
}
|
||||
}
|
||||
parserState.pos += 1;
|
||||
@ -351,8 +351,13 @@ function initSearch(rawSearchIndex) {
|
||||
if (parserState.typeFilter === null) {
|
||||
parserState.typeFilter = "macro";
|
||||
} else if (parserState.typeFilter !== "macro") {
|
||||
throw new Error("Invalid search type: macro `!` and " +
|
||||
`\`${parserState.typeFilter}\` both specified`);
|
||||
throw [
|
||||
"Invalid search type: macro ",
|
||||
"!",
|
||||
" and ",
|
||||
parserState.typeFilter,
|
||||
" both specified",
|
||||
];
|
||||
}
|
||||
end = foundExclamation;
|
||||
}
|
||||
@ -382,9 +387,9 @@ function initSearch(rawSearchIndex) {
|
||||
parserState.userQuery[parserState.pos] === "<"
|
||||
) {
|
||||
if (isInGenerics) {
|
||||
throw new Error("Unexpected `<` after `<`");
|
||||
throw ["Unexpected ", "<", " after ", "<"];
|
||||
} else if (start >= end) {
|
||||
throw new Error("Found generics without a path");
|
||||
throw ["Found generics without a path"];
|
||||
}
|
||||
parserState.pos += 1;
|
||||
getItemsBefore(query, parserState, generics, ">");
|
||||
@ -428,21 +433,39 @@ function initSearch(rawSearchIndex) {
|
||||
foundStopChar = true;
|
||||
continue;
|
||||
} else if (c === ":" && isPathStart(parserState)) {
|
||||
throw new Error("Unexpected `::`: paths cannot start with `::`");
|
||||
throw ["Unexpected ", "::", ": paths cannot start with ", "::"];
|
||||
} else if (c === ":" || isEndCharacter(c)) {
|
||||
let extra = "";
|
||||
if (endChar === ">") {
|
||||
extra = "`<`";
|
||||
extra = "<";
|
||||
} else if (endChar === "") {
|
||||
extra = "`->`";
|
||||
extra = "->";
|
||||
} else {
|
||||
extra = endChar;
|
||||
}
|
||||
throw new Error("Unexpected `" + c + "` after " + extra);
|
||||
throw ["Unexpected ", c, " after ", extra];
|
||||
}
|
||||
if (!foundStopChar) {
|
||||
if (endChar !== "") {
|
||||
throw new Error(`Expected \`,\`, \` \` or \`${endChar}\`, found \`${c}\``);
|
||||
throw [
|
||||
"Expected ",
|
||||
",", // comma
|
||||
", ",
|
||||
" ", // whitespace
|
||||
" or ",
|
||||
endChar,
|
||||
", found ",
|
||||
c,
|
||||
];
|
||||
}
|
||||
throw new Error(`Expected \`,\` or \` \`, found \`${c}\``);
|
||||
throw [
|
||||
"Expected ",
|
||||
",", // comma
|
||||
" or ",
|
||||
" ", // whitespace
|
||||
", found ",
|
||||
c,
|
||||
];
|
||||
}
|
||||
const posBefore = parserState.pos;
|
||||
getNextElem(query, parserState, elems, endChar === ">");
|
||||
@ -470,7 +493,7 @@ function initSearch(rawSearchIndex) {
|
||||
|
||||
for (let pos = 0; pos < parserState.pos; ++pos) {
|
||||
if (!isIdentCharacter(query[pos]) && !isWhitespaceCharacter(query[pos])) {
|
||||
throw new Error(`Unexpected \`${query[pos]}\` in type filter`);
|
||||
throw ["Unexpected ", query[pos], " in type filter"];
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -496,19 +519,19 @@ function initSearch(rawSearchIndex) {
|
||||
if (isReturnArrow(parserState)) {
|
||||
break;
|
||||
}
|
||||
throw new Error(`Unexpected \`${c}\` (did you mean \`->\`?)`);
|
||||
throw ["Unexpected ", c, " (did you mean ", "->", "?)"];
|
||||
}
|
||||
throw new Error(`Unexpected \`${c}\``);
|
||||
throw ["Unexpected ", c];
|
||||
} else if (c === ":" && !isPathStart(parserState)) {
|
||||
if (parserState.typeFilter !== null) {
|
||||
throw new Error("Unexpected `:`");
|
||||
throw ["Unexpected ", ":"];
|
||||
}
|
||||
if (query.elems.length === 0) {
|
||||
throw new Error("Expected type filter before `:`");
|
||||
throw ["Expected type filter before ", ":"];
|
||||
} else if (query.elems.length !== 1 || parserState.totalElems !== 1) {
|
||||
throw new Error("Unexpected `:`");
|
||||
throw ["Unexpected ", ":"];
|
||||
} else if (query.literalSearch) {
|
||||
throw new Error("You cannot use quotes on type filter");
|
||||
throw ["You cannot use quotes on type filter"];
|
||||
}
|
||||
checkExtraTypeFilterCharacters(parserState);
|
||||
// The type filter doesn't count as an element since it's a modifier.
|
||||
@ -521,9 +544,29 @@ function initSearch(rawSearchIndex) {
|
||||
}
|
||||
if (!foundStopChar) {
|
||||
if (parserState.typeFilter !== null) {
|
||||
throw new Error(`Expected \`,\`, \` \` or \`->\`, found \`${c}\``);
|
||||
throw [
|
||||
"Expected ",
|
||||
",", // comma
|
||||
", ",
|
||||
" ", // whitespace
|
||||
" or ",
|
||||
"->", // arrow
|
||||
", found ",
|
||||
c,
|
||||
];
|
||||
}
|
||||
throw new Error(`Expected \`,\`, \` \`, \`:\` or \`->\`, found \`${c}\``);
|
||||
throw [
|
||||
"Expected ",
|
||||
",", // comma
|
||||
", ",
|
||||
" ", // whitespace
|
||||
", ",
|
||||
":", // colon
|
||||
" or ",
|
||||
"->", // arrow
|
||||
", found ",
|
||||
c,
|
||||
];
|
||||
}
|
||||
const before = query.elems.length;
|
||||
getNextElem(query, parserState, query.elems, false);
|
||||
@ -540,7 +583,7 @@ function initSearch(rawSearchIndex) {
|
||||
getItemsBefore(query, parserState, query.returned, "");
|
||||
// Nothing can come afterward!
|
||||
if (query.returned.length === 0) {
|
||||
throw new Error("Expected at least one item after `->`");
|
||||
throw ["Expected at least one item after ", "->"];
|
||||
}
|
||||
break;
|
||||
} else {
|
||||
@ -694,7 +737,7 @@ function initSearch(rawSearchIndex) {
|
||||
}
|
||||
} catch (err) {
|
||||
query = newParsedQuery(userQuery);
|
||||
query.error = err.message;
|
||||
query.error = err;
|
||||
query.typeFilter = -1;
|
||||
return query;
|
||||
}
|
||||
@ -1760,7 +1803,16 @@ function initSearch(rawSearchIndex) {
|
||||
|
||||
let output = `<h1 class="search-results-title">Results${crates}</h1>`;
|
||||
if (results.query.error !== null) {
|
||||
output += `<h3>Query parser error: "${results.query.error}".</h3>`;
|
||||
const error = results.query.error;
|
||||
error.forEach((value, index) => {
|
||||
value = value.split("<").join("<").split(">").join(">");
|
||||
if (index % 2 !== 0) {
|
||||
error[index] = `<code>${value}</code>`;
|
||||
} else {
|
||||
error[index] = value;
|
||||
}
|
||||
});
|
||||
output += `<h3 class="error">Query parser error: "${error.join("")}".</h3>`;
|
||||
output += "<div id=\"search-tabs\">" +
|
||||
makeTabHeader(0, "In Names", ret_others[1]) +
|
||||
"</div>";
|
||||
|
@ -777,10 +777,11 @@ impl<'mir, 'tcx> Machine<'mir, 'tcx> for MiriMachine<'mir, 'tcx> {
|
||||
|
||||
type Provenance = Provenance;
|
||||
type ProvenanceExtra = ProvenanceExtra;
|
||||
type Bytes = Box<[u8]>;
|
||||
|
||||
type MemoryMap = MonoHashMap<
|
||||
AllocId,
|
||||
(MemoryKind<MiriMemoryKind>, Allocation<Provenance, Self::AllocExtra>),
|
||||
(MemoryKind<MiriMemoryKind>, Allocation<Provenance, Self::AllocExtra, Self::Bytes>),
|
||||
>;
|
||||
|
||||
const GLOBAL_KIND: Option<MiriMemoryKind> = Some(MiriMemoryKind::Global);
|
||||
|
@ -138,8 +138,20 @@ function valueCheck(fullPath, expected, result, error_text, queryName) {
|
||||
error_text.push('==> Unknown key "' + key + '"');
|
||||
break;
|
||||
}
|
||||
let result_v = result[key];
|
||||
if (result_v !== null && key === "error") {
|
||||
result_v.forEach((value, index) => {
|
||||
value = value.split(" ").join(" ");
|
||||
if (index % 2 === 1) {
|
||||
result_v[index] = "`" + value + "`";
|
||||
} else {
|
||||
result_v[index] = value;
|
||||
}
|
||||
});
|
||||
result_v = result_v.join("");
|
||||
}
|
||||
const obj_path = fullPath + (fullPath.length > 0 ? '.' : '') + key;
|
||||
valueCheck(obj_path, expected[key], result[key], error_text, queryName);
|
||||
valueCheck(obj_path, expected[key], result_v, error_text, queryName);
|
||||
}
|
||||
} else {
|
||||
expectedValue = JSON.stringify(expected);
|
||||
|
39
tests/rustdoc-gui/search-error.goml
Normal file
39
tests/rustdoc-gui/search-error.goml
Normal file
@ -0,0 +1,39 @@
|
||||
// Checks that the crate search filtering is handled correctly and changes the results.
|
||||
goto: "file://" + |DOC_PATH| + "/test_docs/index.html?search=sa'%3Bda'%3Bds"
|
||||
show-text: true
|
||||
|
||||
define-function: (
|
||||
"check-colors",
|
||||
(theme, error_background),
|
||||
block {
|
||||
// Setting the theme.
|
||||
local-storage: {"rustdoc-theme": |theme|, "rustdoc-use-system-theme": "false"}
|
||||
// We reload the page so the local storage settings are being used.
|
||||
reload:
|
||||
|
||||
wait-for: "#search .error code"
|
||||
assert-css: ("#search .error code", {"background-color": |error_background|})
|
||||
}
|
||||
)
|
||||
|
||||
call-function: (
|
||||
"check-colors",
|
||||
{
|
||||
"theme": "ayu",
|
||||
"error_background": "rgb(79, 76, 76)",
|
||||
},
|
||||
)
|
||||
call-function: (
|
||||
"check-colors",
|
||||
{
|
||||
"theme": "dark",
|
||||
"error_background": "rgb(72, 72, 72)",
|
||||
},
|
||||
)
|
||||
call-function: (
|
||||
"check-colors",
|
||||
{
|
||||
"theme": "light",
|
||||
"error_background": "rgb(208, 204, 204)",
|
||||
},
|
||||
)
|
@ -67,7 +67,7 @@ const PARSED = [
|
||||
returned: [],
|
||||
typeFilter: -1,
|
||||
userQuery: "a<\"p\">",
|
||||
error: "`\"` cannot be used in generics",
|
||||
error: "Unexpected `\"` in generics",
|
||||
},
|
||||
{
|
||||
elems: [],
|
||||
@ -373,7 +373,7 @@ const PARSED = [
|
||||
returned: [],
|
||||
typeFilter: -1,
|
||||
userQuery: "a!a",
|
||||
error: '`!` can only be at the end of an ident',
|
||||
error: 'Unexpected `!`: it can only be at the end of an ident',
|
||||
},
|
||||
{
|
||||
elems: [],
|
||||
|
@ -18,11 +18,85 @@ struct Burrito<F> {
|
||||
filling: F,
|
||||
}
|
||||
|
||||
impl<It: Iterator> T1 for Option<It> {}
|
||||
|
||||
impl<'a, A: T1> T1 for &'a A {}
|
||||
|
||||
fn want<V: T1>(_x: V) {}
|
||||
|
||||
enum ExampleTuple<T> {
|
||||
ExampleTupleVariant(T),
|
||||
}
|
||||
use ExampleDifferentTupleVariantName as ExampleYetAnotherTupleVariantName;
|
||||
use ExampleTuple as ExampleOtherTuple;
|
||||
use ExampleTuple::ExampleTupleVariant as ExampleDifferentTupleVariantName;
|
||||
use ExampleTuple::*;
|
||||
|
||||
impl<A> T1 for ExampleTuple<A> where A: T3 {}
|
||||
|
||||
enum ExampleStruct<T> {
|
||||
ExampleStructVariant { field: T },
|
||||
}
|
||||
use ExampleDifferentStructVariantName as ExampleYetAnotherStructVariantName;
|
||||
use ExampleStruct as ExampleOtherStruct;
|
||||
use ExampleStruct::ExampleStructVariant as ExampleDifferentStructVariantName;
|
||||
use ExampleStruct::*;
|
||||
|
||||
impl<A> T1 for ExampleStruct<A> where A: T3 {}
|
||||
|
||||
struct ExampleActuallyTupleStruct<T>(T, i32);
|
||||
use ExampleActuallyTupleStruct as ExampleActuallyTupleStructOther;
|
||||
|
||||
impl<A> T1 for ExampleActuallyTupleStruct<A> where A: T3 {}
|
||||
|
||||
fn example<Q>(q: Q) {
|
||||
want(Wrapper { value: Burrito { filling: q } });
|
||||
//~^ ERROR the trait bound `Q: T3` is not satisfied [E0277]
|
||||
|
||||
want(Some(()));
|
||||
//~^ ERROR `()` is not an iterator [E0277]
|
||||
|
||||
want(Some(q));
|
||||
//~^ ERROR `Q` is not an iterator [E0277]
|
||||
|
||||
want(&Some(q));
|
||||
//~^ ERROR `Q` is not an iterator [E0277]
|
||||
|
||||
want(&ExampleTuple::ExampleTupleVariant(q));
|
||||
//~^ ERROR `Q: T3` is not satisfied [E0277]
|
||||
|
||||
want(&ExampleTupleVariant(q));
|
||||
//~^ ERROR `Q: T3` is not satisfied [E0277]
|
||||
|
||||
want(&ExampleOtherTuple::ExampleTupleVariant(q));
|
||||
//~^ ERROR `Q: T3` is not satisfied [E0277]
|
||||
|
||||
want(&ExampleDifferentTupleVariantName(q));
|
||||
//~^ ERROR `Q: T3` is not satisfied [E0277]
|
||||
|
||||
want(&ExampleYetAnotherTupleVariantName(q));
|
||||
//~^ ERROR `Q: T3` is not satisfied [E0277]
|
||||
|
||||
want(&ExampleStruct::ExampleStructVariant { field: q });
|
||||
//~^ ERROR `Q: T3` is not satisfied [E0277]
|
||||
|
||||
want(&ExampleStructVariant { field: q });
|
||||
//~^ ERROR `Q: T3` is not satisfied [E0277]
|
||||
|
||||
want(&ExampleOtherStruct::ExampleStructVariant { field: q });
|
||||
//~^ ERROR `Q: T3` is not satisfied [E0277]
|
||||
|
||||
want(&ExampleDifferentStructVariantName { field: q });
|
||||
//~^ ERROR `Q: T3` is not satisfied [E0277]
|
||||
|
||||
want(&ExampleYetAnotherStructVariantName { field: q });
|
||||
//~^ ERROR `Q: T3` is not satisfied [E0277]
|
||||
|
||||
want(&ExampleActuallyTupleStruct(q, 0));
|
||||
//~^ ERROR `Q: T3` is not satisfied [E0277]
|
||||
|
||||
want(&ExampleActuallyTupleStructOther(q, 0));
|
||||
//~^ ERROR `Q: T3` is not satisfied [E0277]
|
||||
}
|
||||
|
||||
fn main() {}
|
||||
|
@ -1,5 +1,5 @@
|
||||
error[E0277]: the trait bound `Q: T3` is not satisfied
|
||||
--> $DIR/blame-trait-error.rs:24:46
|
||||
--> $DIR/blame-trait-error.rs:53:46
|
||||
|
|
||||
LL | want(Wrapper { value: Burrito { filling: q } });
|
||||
| ---- ^ the trait `T3` is not implemented for `Q`
|
||||
@ -21,7 +21,7 @@ LL | impl<B: T2> T1 for Wrapper<B> {}
|
||||
| |
|
||||
| unsatisfied trait bound introduced here
|
||||
note: required by a bound in `want`
|
||||
--> $DIR/blame-trait-error.rs:21:12
|
||||
--> $DIR/blame-trait-error.rs:25:12
|
||||
|
|
||||
LL | fn want<V: T1>(_x: V) {}
|
||||
| ^^ required by this bound in `want`
|
||||
@ -30,6 +30,373 @@ help: consider restricting type parameter `Q`
|
||||
LL | fn example<Q: T3>(q: Q) {
|
||||
| ++++
|
||||
|
||||
error: aborting due to previous error
|
||||
error[E0277]: `()` is not an iterator
|
||||
--> $DIR/blame-trait-error.rs:56:15
|
||||
|
|
||||
LL | want(Some(()));
|
||||
| ---- ^^ `()` is not an iterator
|
||||
| |
|
||||
| required by a bound introduced by this call
|
||||
|
|
||||
= help: the trait `Iterator` is not implemented for `()`
|
||||
= help: the trait `T1` is implemented for `Option<It>`
|
||||
note: required for `Option<()>` to implement `T1`
|
||||
--> $DIR/blame-trait-error.rs:21:20
|
||||
|
|
||||
LL | impl<It: Iterator> T1 for Option<It> {}
|
||||
| -------- ^^ ^^^^^^^^^^
|
||||
| |
|
||||
| unsatisfied trait bound introduced here
|
||||
note: required by a bound in `want`
|
||||
--> $DIR/blame-trait-error.rs:25:12
|
||||
|
|
||||
LL | fn want<V: T1>(_x: V) {}
|
||||
| ^^ required by this bound in `want`
|
||||
|
||||
error[E0277]: `Q` is not an iterator
|
||||
--> $DIR/blame-trait-error.rs:59:15
|
||||
|
|
||||
LL | want(Some(q));
|
||||
| ---- ^ `Q` is not an iterator
|
||||
| |
|
||||
| required by a bound introduced by this call
|
||||
|
|
||||
note: required for `Option<Q>` to implement `T1`
|
||||
--> $DIR/blame-trait-error.rs:21:20
|
||||
|
|
||||
LL | impl<It: Iterator> T1 for Option<It> {}
|
||||
| -------- ^^ ^^^^^^^^^^
|
||||
| |
|
||||
| unsatisfied trait bound introduced here
|
||||
note: required by a bound in `want`
|
||||
--> $DIR/blame-trait-error.rs:25:12
|
||||
|
|
||||
LL | fn want<V: T1>(_x: V) {}
|
||||
| ^^ required by this bound in `want`
|
||||
help: consider restricting type parameter `Q`
|
||||
|
|
||||
LL | fn example<Q: std::iter::Iterator>(q: Q) {
|
||||
| +++++++++++++++++++++
|
||||
|
||||
error[E0277]: `Q` is not an iterator
|
||||
--> $DIR/blame-trait-error.rs:62:16
|
||||
|
|
||||
LL | want(&Some(q));
|
||||
| ---- ^ `Q` is not an iterator
|
||||
| |
|
||||
| required by a bound introduced by this call
|
||||
|
|
||||
note: required for `Option<Q>` to implement `T1`
|
||||
--> $DIR/blame-trait-error.rs:21:20
|
||||
|
|
||||
LL | impl<It: Iterator> T1 for Option<It> {}
|
||||
| -------- ^^ ^^^^^^^^^^
|
||||
| |
|
||||
| unsatisfied trait bound introduced here
|
||||
= note: 1 redundant requirement hidden
|
||||
= note: required for `&Option<Q>` to implement `T1`
|
||||
note: required by a bound in `want`
|
||||
--> $DIR/blame-trait-error.rs:25:12
|
||||
|
|
||||
LL | fn want<V: T1>(_x: V) {}
|
||||
| ^^ required by this bound in `want`
|
||||
help: consider restricting type parameter `Q`
|
||||
|
|
||||
LL | fn example<Q: std::iter::Iterator>(q: Q) {
|
||||
| +++++++++++++++++++++
|
||||
|
||||
error[E0277]: the trait bound `Q: T3` is not satisfied
|
||||
--> $DIR/blame-trait-error.rs:65:45
|
||||
|
|
||||
LL | want(&ExampleTuple::ExampleTupleVariant(q));
|
||||
| ---- ^ the trait `T3` is not implemented for `Q`
|
||||
| |
|
||||
| required by a bound introduced by this call
|
||||
|
|
||||
note: required for `ExampleTuple<Q>` to implement `T1`
|
||||
--> $DIR/blame-trait-error.rs:35:9
|
||||
|
|
||||
LL | impl<A> T1 for ExampleTuple<A> where A: T3 {}
|
||||
| ^^ ^^^^^^^^^^^^^^^ -- unsatisfied trait bound introduced here
|
||||
= note: 1 redundant requirement hidden
|
||||
= note: required for `&ExampleTuple<Q>` to implement `T1`
|
||||
note: required by a bound in `want`
|
||||
--> $DIR/blame-trait-error.rs:25:12
|
||||
|
|
||||
LL | fn want<V: T1>(_x: V) {}
|
||||
| ^^ required by this bound in `want`
|
||||
help: consider restricting type parameter `Q`
|
||||
|
|
||||
LL | fn example<Q: T3>(q: Q) {
|
||||
| ++++
|
||||
|
||||
error[E0277]: the trait bound `Q: T3` is not satisfied
|
||||
--> $DIR/blame-trait-error.rs:68:31
|
||||
|
|
||||
LL | want(&ExampleTupleVariant(q));
|
||||
| ---- ^ the trait `T3` is not implemented for `Q`
|
||||
| |
|
||||
| required by a bound introduced by this call
|
||||
|
|
||||
note: required for `ExampleTuple<Q>` to implement `T1`
|
||||
--> $DIR/blame-trait-error.rs:35:9
|
||||
|
|
||||
LL | impl<A> T1 for ExampleTuple<A> where A: T3 {}
|
||||
| ^^ ^^^^^^^^^^^^^^^ -- unsatisfied trait bound introduced here
|
||||
= note: 1 redundant requirement hidden
|
||||
= note: required for `&ExampleTuple<Q>` to implement `T1`
|
||||
note: required by a bound in `want`
|
||||
--> $DIR/blame-trait-error.rs:25:12
|
||||
|
|
||||
LL | fn want<V: T1>(_x: V) {}
|
||||
| ^^ required by this bound in `want`
|
||||
help: consider restricting type parameter `Q`
|
||||
|
|
||||
LL | fn example<Q: T3>(q: Q) {
|
||||
| ++++
|
||||
|
||||
error[E0277]: the trait bound `Q: T3` is not satisfied
|
||||
--> $DIR/blame-trait-error.rs:71:50
|
||||
|
|
||||
LL | want(&ExampleOtherTuple::ExampleTupleVariant(q));
|
||||
| ---- ^ the trait `T3` is not implemented for `Q`
|
||||
| |
|
||||
| required by a bound introduced by this call
|
||||
|
|
||||
note: required for `ExampleTuple<Q>` to implement `T1`
|
||||
--> $DIR/blame-trait-error.rs:35:9
|
||||
|
|
||||
LL | impl<A> T1 for ExampleTuple<A> where A: T3 {}
|
||||
| ^^ ^^^^^^^^^^^^^^^ -- unsatisfied trait bound introduced here
|
||||
= note: 1 redundant requirement hidden
|
||||
= note: required for `&ExampleTuple<Q>` to implement `T1`
|
||||
note: required by a bound in `want`
|
||||
--> $DIR/blame-trait-error.rs:25:12
|
||||
|
|
||||
LL | fn want<V: T1>(_x: V) {}
|
||||
| ^^ required by this bound in `want`
|
||||
help: consider restricting type parameter `Q`
|
||||
|
|
||||
LL | fn example<Q: T3>(q: Q) {
|
||||
| ++++
|
||||
|
||||
error[E0277]: the trait bound `Q: T3` is not satisfied
|
||||
--> $DIR/blame-trait-error.rs:74:44
|
||||
|
|
||||
LL | want(&ExampleDifferentTupleVariantName(q));
|
||||
| ---- ^ the trait `T3` is not implemented for `Q`
|
||||
| |
|
||||
| required by a bound introduced by this call
|
||||
|
|
||||
note: required for `ExampleTuple<Q>` to implement `T1`
|
||||
--> $DIR/blame-trait-error.rs:35:9
|
||||
|
|
||||
LL | impl<A> T1 for ExampleTuple<A> where A: T3 {}
|
||||
| ^^ ^^^^^^^^^^^^^^^ -- unsatisfied trait bound introduced here
|
||||
= note: 1 redundant requirement hidden
|
||||
= note: required for `&ExampleTuple<Q>` to implement `T1`
|
||||
note: required by a bound in `want`
|
||||
--> $DIR/blame-trait-error.rs:25:12
|
||||
|
|
||||
LL | fn want<V: T1>(_x: V) {}
|
||||
| ^^ required by this bound in `want`
|
||||
help: consider restricting type parameter `Q`
|
||||
|
|
||||
LL | fn example<Q: T3>(q: Q) {
|
||||
| ++++
|
||||
|
||||
error[E0277]: the trait bound `Q: T3` is not satisfied
|
||||
--> $DIR/blame-trait-error.rs:77:45
|
||||
|
|
||||
LL | want(&ExampleYetAnotherTupleVariantName(q));
|
||||
| ---- ^ the trait `T3` is not implemented for `Q`
|
||||
| |
|
||||
| required by a bound introduced by this call
|
||||
|
|
||||
note: required for `ExampleTuple<Q>` to implement `T1`
|
||||
--> $DIR/blame-trait-error.rs:35:9
|
||||
|
|
||||
LL | impl<A> T1 for ExampleTuple<A> where A: T3 {}
|
||||
| ^^ ^^^^^^^^^^^^^^^ -- unsatisfied trait bound introduced here
|
||||
= note: 1 redundant requirement hidden
|
||||
= note: required for `&ExampleTuple<Q>` to implement `T1`
|
||||
note: required by a bound in `want`
|
||||
--> $DIR/blame-trait-error.rs:25:12
|
||||
|
|
||||
LL | fn want<V: T1>(_x: V) {}
|
||||
| ^^ required by this bound in `want`
|
||||
help: consider restricting type parameter `Q`
|
||||
|
|
||||
LL | fn example<Q: T3>(q: Q) {
|
||||
| ++++
|
||||
|
||||
error[E0277]: the trait bound `Q: T3` is not satisfied
|
||||
--> $DIR/blame-trait-error.rs:80:56
|
||||
|
|
||||
LL | want(&ExampleStruct::ExampleStructVariant { field: q });
|
||||
| ---- required by a bound introduced by this call ^ the trait `T3` is not implemented for `Q`
|
||||
|
|
||||
note: required for `ExampleStruct<Q>` to implement `T1`
|
||||
--> $DIR/blame-trait-error.rs:45:9
|
||||
|
|
||||
LL | impl<A> T1 for ExampleStruct<A> where A: T3 {}
|
||||
| ^^ ^^^^^^^^^^^^^^^^ -- unsatisfied trait bound introduced here
|
||||
= note: 1 redundant requirement hidden
|
||||
= note: required for `&ExampleStruct<Q>` to implement `T1`
|
||||
note: required by a bound in `want`
|
||||
--> $DIR/blame-trait-error.rs:25:12
|
||||
|
|
||||
LL | fn want<V: T1>(_x: V) {}
|
||||
| ^^ required by this bound in `want`
|
||||
help: consider restricting type parameter `Q`
|
||||
|
|
||||
LL | fn example<Q: T3>(q: Q) {
|
||||
| ++++
|
||||
|
||||
error[E0277]: the trait bound `Q: T3` is not satisfied
|
||||
--> $DIR/blame-trait-error.rs:83:41
|
||||
|
|
||||
LL | want(&ExampleStructVariant { field: q });
|
||||
| ---- ^ the trait `T3` is not implemented for `Q`
|
||||
| |
|
||||
| required by a bound introduced by this call
|
||||
|
|
||||
note: required for `ExampleStruct<Q>` to implement `T1`
|
||||
--> $DIR/blame-trait-error.rs:45:9
|
||||
|
|
||||
LL | impl<A> T1 for ExampleStruct<A> where A: T3 {}
|
||||
| ^^ ^^^^^^^^^^^^^^^^ -- unsatisfied trait bound introduced here
|
||||
= note: 1 redundant requirement hidden
|
||||
= note: required for `&ExampleStruct<Q>` to implement `T1`
|
||||
note: required by a bound in `want`
|
||||
--> $DIR/blame-trait-error.rs:25:12
|
||||
|
|
||||
LL | fn want<V: T1>(_x: V) {}
|
||||
| ^^ required by this bound in `want`
|
||||
help: consider restricting type parameter `Q`
|
||||
|
|
||||
LL | fn example<Q: T3>(q: Q) {
|
||||
| ++++
|
||||
|
||||
error[E0277]: the trait bound `Q: T3` is not satisfied
|
||||
--> $DIR/blame-trait-error.rs:86:61
|
||||
|
|
||||
LL | want(&ExampleOtherStruct::ExampleStructVariant { field: q });
|
||||
| ---- required by a bound introduced by this call ^ the trait `T3` is not implemented for `Q`
|
||||
|
|
||||
note: required for `ExampleStruct<Q>` to implement `T1`
|
||||
--> $DIR/blame-trait-error.rs:45:9
|
||||
|
|
||||
LL | impl<A> T1 for ExampleStruct<A> where A: T3 {}
|
||||
| ^^ ^^^^^^^^^^^^^^^^ -- unsatisfied trait bound introduced here
|
||||
= note: 1 redundant requirement hidden
|
||||
= note: required for `&ExampleStruct<Q>` to implement `T1`
|
||||
note: required by a bound in `want`
|
||||
--> $DIR/blame-trait-error.rs:25:12
|
||||
|
|
||||
LL | fn want<V: T1>(_x: V) {}
|
||||
| ^^ required by this bound in `want`
|
||||
help: consider restricting type parameter `Q`
|
||||
|
|
||||
LL | fn example<Q: T3>(q: Q) {
|
||||
| ++++
|
||||
|
||||
error[E0277]: the trait bound `Q: T3` is not satisfied
|
||||
--> $DIR/blame-trait-error.rs:89:54
|
||||
|
|
||||
LL | want(&ExampleDifferentStructVariantName { field: q });
|
||||
| ---- required by a bound introduced by this call ^ the trait `T3` is not implemented for `Q`
|
||||
|
|
||||
note: required for `ExampleStruct<Q>` to implement `T1`
|
||||
--> $DIR/blame-trait-error.rs:45:9
|
||||
|
|
||||
LL | impl<A> T1 for ExampleStruct<A> where A: T3 {}
|
||||
| ^^ ^^^^^^^^^^^^^^^^ -- unsatisfied trait bound introduced here
|
||||
= note: 1 redundant requirement hidden
|
||||
= note: required for `&ExampleStruct<Q>` to implement `T1`
|
||||
note: required by a bound in `want`
|
||||
--> $DIR/blame-trait-error.rs:25:12
|
||||
|
|
||||
LL | fn want<V: T1>(_x: V) {}
|
||||
| ^^ required by this bound in `want`
|
||||
help: consider restricting type parameter `Q`
|
||||
|
|
||||
LL | fn example<Q: T3>(q: Q) {
|
||||
| ++++
|
||||
|
||||
error[E0277]: the trait bound `Q: T3` is not satisfied
|
||||
--> $DIR/blame-trait-error.rs:92:55
|
||||
|
|
||||
LL | want(&ExampleYetAnotherStructVariantName { field: q });
|
||||
| ---- required by a bound introduced by this call ^ the trait `T3` is not implemented for `Q`
|
||||
|
|
||||
note: required for `ExampleStruct<Q>` to implement `T1`
|
||||
--> $DIR/blame-trait-error.rs:45:9
|
||||
|
|
||||
LL | impl<A> T1 for ExampleStruct<A> where A: T3 {}
|
||||
| ^^ ^^^^^^^^^^^^^^^^ -- unsatisfied trait bound introduced here
|
||||
= note: 1 redundant requirement hidden
|
||||
= note: required for `&ExampleStruct<Q>` to implement `T1`
|
||||
note: required by a bound in `want`
|
||||
--> $DIR/blame-trait-error.rs:25:12
|
||||
|
|
||||
LL | fn want<V: T1>(_x: V) {}
|
||||
| ^^ required by this bound in `want`
|
||||
help: consider restricting type parameter `Q`
|
||||
|
|
||||
LL | fn example<Q: T3>(q: Q) {
|
||||
| ++++
|
||||
|
||||
error[E0277]: the trait bound `Q: T3` is not satisfied
|
||||
--> $DIR/blame-trait-error.rs:95:38
|
||||
|
|
||||
LL | want(&ExampleActuallyTupleStruct(q, 0));
|
||||
| ---- ^ the trait `T3` is not implemented for `Q`
|
||||
| |
|
||||
| required by a bound introduced by this call
|
||||
|
|
||||
note: required for `ExampleActuallyTupleStruct<Q>` to implement `T1`
|
||||
--> $DIR/blame-trait-error.rs:50:9
|
||||
|
|
||||
LL | impl<A> T1 for ExampleActuallyTupleStruct<A> where A: T3 {}
|
||||
| ^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -- unsatisfied trait bound introduced here
|
||||
= note: 1 redundant requirement hidden
|
||||
= note: required for `&ExampleActuallyTupleStruct<Q>` to implement `T1`
|
||||
note: required by a bound in `want`
|
||||
--> $DIR/blame-trait-error.rs:25:12
|
||||
|
|
||||
LL | fn want<V: T1>(_x: V) {}
|
||||
| ^^ required by this bound in `want`
|
||||
help: consider restricting type parameter `Q`
|
||||
|
|
||||
LL | fn example<Q: T3>(q: Q) {
|
||||
| ++++
|
||||
|
||||
error[E0277]: the trait bound `Q: T3` is not satisfied
|
||||
--> $DIR/blame-trait-error.rs:98:43
|
||||
|
|
||||
LL | want(&ExampleActuallyTupleStructOther(q, 0));
|
||||
| ---- ^ the trait `T3` is not implemented for `Q`
|
||||
| |
|
||||
| required by a bound introduced by this call
|
||||
|
|
||||
note: required for `ExampleActuallyTupleStruct<Q>` to implement `T1`
|
||||
--> $DIR/blame-trait-error.rs:50:9
|
||||
|
|
||||
LL | impl<A> T1 for ExampleActuallyTupleStruct<A> where A: T3 {}
|
||||
| ^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -- unsatisfied trait bound introduced here
|
||||
= note: 1 redundant requirement hidden
|
||||
= note: required for `&ExampleActuallyTupleStruct<Q>` to implement `T1`
|
||||
note: required by a bound in `want`
|
||||
--> $DIR/blame-trait-error.rs:25:12
|
||||
|
|
||||
LL | fn want<V: T1>(_x: V) {}
|
||||
| ^^ required by this bound in `want`
|
||||
help: consider restricting type parameter `Q`
|
||||
|
|
||||
LL | fn example<Q: T3>(q: Q) {
|
||||
| ++++
|
||||
|
||||
error: aborting due to 16 previous errors
|
||||
|
||||
For more information about this error, try `rustc --explain E0277`.
|
||||
|
@ -91,10 +91,10 @@ LL | fn example<Q: T3>(q: Q) {
|
||||
| ++++
|
||||
|
||||
error[E0277]: the trait bound `Q: T3` is not satisfied
|
||||
--> $DIR/blame-trait-error-spans-on-exprs.rs:93:27
|
||||
--> $DIR/blame-trait-error-spans-on-exprs.rs:93:53
|
||||
|
|
||||
LL | want(Wrapper { value: TacoKinds::OneTaco(false, q) });
|
||||
| ---- ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `T3` is not implemented for `Q`
|
||||
| ---- ^ the trait `T3` is not implemented for `Q`
|
||||
| |
|
||||
| required by a bound introduced by this call
|
||||
|
|
||||
|
@ -1,4 +1,4 @@
|
||||
fn main() {
|
||||
env!("__HOPEFULLY_NOT_DEFINED__");
|
||||
//~^ ERROR: environment variable `__HOPEFULLY_NOT_DEFINED__` not defined
|
||||
env!("CARGO__HOPEFULLY_NOT_DEFINED__");
|
||||
//~^ ERROR: environment variable `CARGO__HOPEFULLY_NOT_DEFINED__` not defined
|
||||
}
|
||||
|
@ -1,9 +1,10 @@
|
||||
error: environment variable `__HOPEFULLY_NOT_DEFINED__` not defined
|
||||
error: environment variable `CARGO__HOPEFULLY_NOT_DEFINED__` not defined at compile time
|
||||
--> $DIR/extenv-not-defined-default.rs:2:5
|
||||
|
|
||||
LL | env!("__HOPEFULLY_NOT_DEFINED__");
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
LL | env!("CARGO__HOPEFULLY_NOT_DEFINED__");
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
= help: Cargo sets build script variables at run time. Use `std::env::var("CARGO__HOPEFULLY_NOT_DEFINED__")` instead
|
||||
= note: this error originates in the macro `env` (in Nightly builds, run with -Z macro-backtrace for more info)
|
||||
|
||||
error: aborting due to previous error
|
||||
|
@ -1,9 +1,10 @@
|
||||
error: environment variable `NON_EXISTENT` not defined
|
||||
error: environment variable `NON_EXISTENT` not defined at compile time
|
||||
--> $DIR/issue-55897.rs:11:22
|
||||
|
|
||||
LL | include!(concat!(env!("NON_EXISTENT"), "/data.rs"));
|
||||
| ^^^^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
= help: Use `std::env::var("NON_EXISTENT")` to read the variable at run time
|
||||
= note: this error originates in the macro `env` (in Nightly builds, run with -Z macro-backtrace for more info)
|
||||
|
||||
error: suffixes on string literals are invalid
|
||||
|
@ -0,0 +1,11 @@
|
||||
// check-pass
|
||||
// compile-flags: -Zlower-impl-trait-in-trait-to-assoc-ty
|
||||
|
||||
#![feature(return_position_impl_trait_in_trait)]
|
||||
#![allow(incomplete_features)]
|
||||
|
||||
trait Foo {
|
||||
fn foo() -> impl Sized;
|
||||
}
|
||||
|
||||
fn main() {}
|
@ -150,18 +150,19 @@ error: expected string literal
|
||||
LL | env!(invalid);
|
||||
| ^^^^^^^
|
||||
|
||||
error: expected string literal
|
||||
--> $DIR/macros-nonfatal-errors.rs:105:10
|
||||
error: env! takes 1 or 2 arguments
|
||||
--> $DIR/macros-nonfatal-errors.rs:105:5
|
||||
|
|
||||
LL | env!(foo, abr, baz);
|
||||
| ^^^
|
||||
| ^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
error: environment variable `RUST_HOPEFULLY_THIS_DOESNT_EXIST` not defined
|
||||
error: environment variable `RUST_HOPEFULLY_THIS_DOESNT_EXIST` not defined at compile time
|
||||
--> $DIR/macros-nonfatal-errors.rs:106:5
|
||||
|
|
||||
LL | env!("RUST_HOPEFULLY_THIS_DOESNT_EXIST");
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
= help: Use `std::env::var("RUST_HOPEFULLY_THIS_DOESNT_EXIST")` to read the variable at run time
|
||||
= note: this error originates in the macro `env` (in Nightly builds, run with -Z macro-backtrace for more info)
|
||||
|
||||
error: format argument must be a string literal
|
||||
|
@ -17,21 +17,16 @@ Thir {
|
||||
],
|
||||
exprs: [
|
||||
Expr {
|
||||
ty: (),
|
||||
temp_lifetime: Some(
|
||||
Node(2),
|
||||
),
|
||||
span: $DIR/thir-flat.rs:4:15: 4:17 (#0),
|
||||
kind: Block {
|
||||
block: b0,
|
||||
},
|
||||
},
|
||||
Expr {
|
||||
ty: (),
|
||||
temp_lifetime: Some(
|
||||
Node(2),
|
||||
),
|
||||
span: $DIR/thir-flat.rs:4:15: 4:17 (#0),
|
||||
},
|
||||
Expr {
|
||||
kind: Scope {
|
||||
region_scope: Node(2),
|
||||
lint_level: Explicit(
|
||||
@ -39,18 +34,23 @@ Thir {
|
||||
),
|
||||
value: e0,
|
||||
},
|
||||
},
|
||||
Expr {
|
||||
ty: (),
|
||||
temp_lifetime: Some(
|
||||
Node(2),
|
||||
),
|
||||
span: $DIR/thir-flat.rs:4:15: 4:17 (#0),
|
||||
},
|
||||
Expr {
|
||||
kind: Scope {
|
||||
region_scope: Destruction(2),
|
||||
lint_level: Inherited,
|
||||
value: e1,
|
||||
},
|
||||
ty: (),
|
||||
temp_lifetime: Some(
|
||||
Node(2),
|
||||
),
|
||||
span: $DIR/thir-flat.rs:4:15: 4:17 (#0),
|
||||
},
|
||||
],
|
||||
stmts: [],
|
||||
|
Loading…
Reference in New Issue
Block a user