mirror of
https://github.com/rust-lang/rust.git
synced 2024-11-22 06:44:35 +00:00
Auto merge of #130768 - compiler-errors:rollup-8ncjy55, r=compiler-errors
Rollup of 7 pull requests Successful merges: - #129545 (rustdoc: redesign toolbar and disclosure widgets) - #130618 (Skip query in get_parent_item when possible.) - #130727 (Check vtable projections for validity in miri) - #130750 (Add new Tier-3 target: `loongarch64-unknown-linux-ohos`) - #130758 (Revert "Add recursion limit to FFI safety lint") - #130759 (Update books) - #130762 (stabilize const_intrinsic_copy) r? `@ghost` `@rustbot` modify labels: rollup
This commit is contained in:
commit
4cadeda932
@ -161,13 +161,13 @@ pub(crate) fn codegen_const_value<'tcx>(
|
||||
fx.module.declare_func_in_func(func_id, &mut fx.bcx.func);
|
||||
fx.bcx.ins().func_addr(fx.pointer_type, local_func_id)
|
||||
}
|
||||
GlobalAlloc::VTable(ty, trait_ref) => {
|
||||
GlobalAlloc::VTable(ty, dyn_ty) => {
|
||||
let data_id = data_id_for_vtable(
|
||||
fx.tcx,
|
||||
&mut fx.constants_cx,
|
||||
fx.module,
|
||||
ty,
|
||||
trait_ref,
|
||||
dyn_ty.principal(),
|
||||
);
|
||||
let local_data_id =
|
||||
fx.module.declare_data_in_func(data_id, &mut fx.bcx.func);
|
||||
@ -456,8 +456,8 @@ fn define_all_allocs(tcx: TyCtxt<'_>, module: &mut dyn Module, cx: &mut Constant
|
||||
GlobalAlloc::Memory(target_alloc) => {
|
||||
data_id_for_alloc_id(cx, module, alloc_id, target_alloc.inner().mutability)
|
||||
}
|
||||
GlobalAlloc::VTable(ty, trait_ref) => {
|
||||
data_id_for_vtable(tcx, cx, module, ty, trait_ref)
|
||||
GlobalAlloc::VTable(ty, dyn_ty) => {
|
||||
data_id_for_vtable(tcx, cx, module, ty, dyn_ty.principal())
|
||||
}
|
||||
GlobalAlloc::Static(def_id) => {
|
||||
if tcx.codegen_fn_attrs(def_id).flags.contains(CodegenFnAttrFlags::THREAD_LOCAL)
|
||||
|
@ -224,10 +224,10 @@ impl<'gcc, 'tcx> ConstCodegenMethods<'tcx> for CodegenCx<'gcc, 'tcx> {
|
||||
value
|
||||
}
|
||||
GlobalAlloc::Function { instance, .. } => self.get_fn_addr(instance),
|
||||
GlobalAlloc::VTable(ty, trait_ref) => {
|
||||
GlobalAlloc::VTable(ty, dyn_ty) => {
|
||||
let alloc = self
|
||||
.tcx
|
||||
.global_alloc(self.tcx.vtable_allocation((ty, trait_ref)))
|
||||
.global_alloc(self.tcx.vtable_allocation((ty, dyn_ty.principal())))
|
||||
.unwrap_memory();
|
||||
let init = const_alloc_to_gcc(self, alloc);
|
||||
self.static_addr_of(init, alloc.inner().align, None)
|
||||
|
@ -290,10 +290,10 @@ impl<'ll, 'tcx> ConstCodegenMethods<'tcx> for CodegenCx<'ll, 'tcx> {
|
||||
self.get_fn_addr(instance.polymorphize(self.tcx)),
|
||||
self.data_layout().instruction_address_space,
|
||||
),
|
||||
GlobalAlloc::VTable(ty, trait_ref) => {
|
||||
GlobalAlloc::VTable(ty, dyn_ty) => {
|
||||
let alloc = self
|
||||
.tcx
|
||||
.global_alloc(self.tcx.vtable_allocation((ty, trait_ref)))
|
||||
.global_alloc(self.tcx.vtable_allocation((ty, dyn_ty.principal())))
|
||||
.unwrap_memory();
|
||||
let init = const_alloc_to_llvm(self, alloc, /*static*/ false);
|
||||
let value = self.static_addr_of(init, alloc.inner().align, None);
|
||||
|
@ -198,7 +198,7 @@ const_eval_invalid_vtable_pointer =
|
||||
using {$pointer} as vtable pointer but it does not point to a vtable
|
||||
|
||||
const_eval_invalid_vtable_trait =
|
||||
using vtable for trait `{$vtable_trait}` but trait `{$expected_trait}` was expected
|
||||
using vtable for `{$vtable_dyn_type}` but `{$expected_dyn_type}` was expected
|
||||
|
||||
const_eval_lazy_lock =
|
||||
consider wrapping this expression in `std::sync::LazyLock::new(|| ...)`
|
||||
@ -459,7 +459,7 @@ const_eval_validation_invalid_fn_ptr = {$front_matter}: encountered {$value}, bu
|
||||
const_eval_validation_invalid_ref_meta = {$front_matter}: encountered invalid reference metadata: total size is bigger than largest supported object
|
||||
const_eval_validation_invalid_ref_slice_meta = {$front_matter}: encountered invalid reference metadata: slice is bigger than largest supported object
|
||||
const_eval_validation_invalid_vtable_ptr = {$front_matter}: encountered {$value}, but expected a vtable pointer
|
||||
const_eval_validation_invalid_vtable_trait = {$front_matter}: wrong trait in wide pointer vtable: expected `{$ref_trait}`, but encountered `{$vtable_trait}`
|
||||
const_eval_validation_invalid_vtable_trait = {$front_matter}: wrong trait in wide pointer vtable: expected `{$expected_dyn_type}`, but encountered `{$vtable_dyn_type}`
|
||||
const_eval_validation_mutable_ref_to_immutable = {$front_matter}: encountered mutable reference or box pointing to read-only memory
|
||||
const_eval_validation_never_val = {$front_matter}: encountered a value of the never type `!`
|
||||
const_eval_validation_null_box = {$front_matter}: encountered a null box
|
||||
|
@ -522,12 +522,9 @@ impl<'a> ReportErrorExt for UndefinedBehaviorInfo<'a> {
|
||||
UnterminatedCString(ptr) | InvalidFunctionPointer(ptr) | InvalidVTablePointer(ptr) => {
|
||||
diag.arg("pointer", ptr);
|
||||
}
|
||||
InvalidVTableTrait { expected_trait, vtable_trait } => {
|
||||
diag.arg("expected_trait", expected_trait.to_string());
|
||||
diag.arg(
|
||||
"vtable_trait",
|
||||
vtable_trait.map(|t| t.to_string()).unwrap_or_else(|| format!("<trivial>")),
|
||||
);
|
||||
InvalidVTableTrait { expected_dyn_type, vtable_dyn_type } => {
|
||||
diag.arg("expected_dyn_type", expected_dyn_type.to_string());
|
||||
diag.arg("vtable_dyn_type", vtable_dyn_type.to_string());
|
||||
}
|
||||
PointerUseAfterFree(alloc_id, msg) => {
|
||||
diag.arg("alloc_id", alloc_id)
|
||||
@ -777,12 +774,9 @@ impl<'tcx> ReportErrorExt for ValidationErrorInfo<'tcx> {
|
||||
DanglingPtrNoProvenance { pointer, .. } => {
|
||||
err.arg("pointer", pointer);
|
||||
}
|
||||
InvalidMetaWrongTrait { expected_trait: ref_trait, vtable_trait } => {
|
||||
err.arg("ref_trait", ref_trait.to_string());
|
||||
err.arg(
|
||||
"vtable_trait",
|
||||
vtable_trait.map(|t| t.to_string()).unwrap_or_else(|| format!("<trivial>")),
|
||||
);
|
||||
InvalidMetaWrongTrait { vtable_dyn_type, expected_dyn_type } => {
|
||||
err.arg("vtable_dyn_type", vtable_dyn_type.to_string());
|
||||
err.arg("expected_dyn_type", expected_dyn_type.to_string());
|
||||
}
|
||||
NullPtr { .. }
|
||||
| ConstRefToMutable
|
||||
|
@ -128,7 +128,7 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> {
|
||||
CastKind::DynStar => {
|
||||
if let ty::Dynamic(data, _, ty::DynStar) = cast_ty.kind() {
|
||||
// Initial cast from sized to dyn trait
|
||||
let vtable = self.get_vtable_ptr(src.layout.ty, data.principal())?;
|
||||
let vtable = self.get_vtable_ptr(src.layout.ty, data)?;
|
||||
let vtable = Scalar::from_maybe_pointer(vtable, self);
|
||||
let data = self.read_immediate(src)?.to_scalar();
|
||||
let _assert_pointer_like = data.to_pointer(self)?;
|
||||
@ -446,12 +446,12 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> {
|
||||
}
|
||||
|
||||
// Get the destination trait vtable and return that.
|
||||
let new_vptr = self.get_vtable_ptr(ty, data_b.principal())?;
|
||||
let new_vptr = self.get_vtable_ptr(ty, data_b)?;
|
||||
self.write_immediate(Immediate::new_dyn_trait(old_data, new_vptr, self), dest)
|
||||
}
|
||||
(_, &ty::Dynamic(data, _, ty::Dyn)) => {
|
||||
// Initial cast from sized to dyn trait
|
||||
let vtable = self.get_vtable_ptr(src_pointee_ty, data.principal())?;
|
||||
let vtable = self.get_vtable_ptr(src_pointee_ty, data)?;
|
||||
let ptr = self.read_pointer(src)?;
|
||||
let val = Immediate::new_dyn_trait(ptr, vtable, &*self.tcx);
|
||||
self.write_immediate(val, dest)
|
||||
|
@ -943,12 +943,13 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> {
|
||||
if offset.bytes() != 0 {
|
||||
throw_ub!(InvalidVTablePointer(Pointer::new(alloc_id, offset)))
|
||||
}
|
||||
let Some(GlobalAlloc::VTable(ty, vtable_trait)) = self.tcx.try_get_global_alloc(alloc_id)
|
||||
let Some(GlobalAlloc::VTable(ty, vtable_dyn_type)) =
|
||||
self.tcx.try_get_global_alloc(alloc_id)
|
||||
else {
|
||||
throw_ub!(InvalidVTablePointer(Pointer::new(alloc_id, offset)))
|
||||
};
|
||||
if let Some(expected_trait) = expected_trait {
|
||||
self.check_vtable_for_type(vtable_trait, expected_trait)?;
|
||||
if let Some(expected_dyn_type) = expected_trait {
|
||||
self.check_vtable_for_type(vtable_dyn_type, expected_dyn_type)?;
|
||||
}
|
||||
Ok(ty)
|
||||
}
|
||||
@ -1113,11 +1114,8 @@ impl<'a, 'tcx, M: Machine<'tcx>> std::fmt::Debug for DumpAllocs<'a, 'tcx, M> {
|
||||
Some(GlobalAlloc::Function { instance, .. }) => {
|
||||
write!(fmt, " (fn: {instance})")?;
|
||||
}
|
||||
Some(GlobalAlloc::VTable(ty, Some(trait_ref))) => {
|
||||
write!(fmt, " (vtable: impl {trait_ref} for {ty})")?;
|
||||
}
|
||||
Some(GlobalAlloc::VTable(ty, None)) => {
|
||||
write!(fmt, " (vtable: impl <auto trait> for {ty})")?;
|
||||
Some(GlobalAlloc::VTable(ty, dyn_ty)) => {
|
||||
write!(fmt, " (vtable: impl {dyn_ty} for {ty})")?;
|
||||
}
|
||||
Some(GlobalAlloc::Static(did)) => {
|
||||
write!(fmt, " (static: {})", self.ecx.tcx.def_path_str(did))?;
|
||||
|
@ -1,6 +1,6 @@
|
||||
use rustc_middle::mir::interpret::{InterpResult, Pointer};
|
||||
use rustc_middle::ty::layout::LayoutOf;
|
||||
use rustc_middle::ty::{self, Ty, TyCtxt, VtblEntry};
|
||||
use rustc_middle::ty::{self, ExistentialPredicateStableCmpExt, Ty, TyCtxt, VtblEntry};
|
||||
use rustc_target::abi::{Align, Size};
|
||||
use tracing::trace;
|
||||
|
||||
@ -11,26 +11,25 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> {
|
||||
/// Creates a dynamic vtable for the given type and vtable origin. This is used only for
|
||||
/// objects.
|
||||
///
|
||||
/// The `trait_ref` encodes the erased self type. Hence, if we are making an object `Foo<Trait>`
|
||||
/// from a value of type `Foo<T>`, then `trait_ref` would map `T: Trait`. `None` here means that
|
||||
/// this is an auto trait without any methods, so we only need the basic vtable (drop, size,
|
||||
/// align).
|
||||
/// The `dyn_ty` encodes the erased self type. Hence, if we are making an object
|
||||
/// `Foo<dyn Trait<Assoc = A> + Send>` from a value of type `Foo<T>`, then `dyn_ty`
|
||||
/// would be `Trait<Assoc = A> + Send`. If this list doesn't have a principal trait ref,
|
||||
/// we only need the basic vtable prefix (drop, size, align).
|
||||
pub fn get_vtable_ptr(
|
||||
&self,
|
||||
ty: Ty<'tcx>,
|
||||
poly_trait_ref: Option<ty::PolyExistentialTraitRef<'tcx>>,
|
||||
dyn_ty: &'tcx ty::List<ty::PolyExistentialPredicate<'tcx>>,
|
||||
) -> InterpResult<'tcx, Pointer<Option<M::Provenance>>> {
|
||||
trace!("get_vtable(trait_ref={:?})", poly_trait_ref);
|
||||
trace!("get_vtable(ty={ty:?}, dyn_ty={dyn_ty:?})");
|
||||
|
||||
let (ty, poly_trait_ref) = self.tcx.erase_regions((ty, poly_trait_ref));
|
||||
let (ty, dyn_ty) = self.tcx.erase_regions((ty, dyn_ty));
|
||||
|
||||
// All vtables must be monomorphic, bail out otherwise.
|
||||
ensure_monomorphic_enough(*self.tcx, ty)?;
|
||||
ensure_monomorphic_enough(*self.tcx, poly_trait_ref)?;
|
||||
ensure_monomorphic_enough(*self.tcx, dyn_ty)?;
|
||||
|
||||
let salt = M::get_global_alloc_salt(self, None);
|
||||
let vtable_symbolic_allocation =
|
||||
self.tcx.reserve_and_set_vtable_alloc(ty, poly_trait_ref, salt);
|
||||
let vtable_symbolic_allocation = self.tcx.reserve_and_set_vtable_alloc(ty, dyn_ty, salt);
|
||||
let vtable_ptr = self.global_root_pointer(Pointer::from(vtable_symbolic_allocation))?;
|
||||
Ok(vtable_ptr.into())
|
||||
}
|
||||
@ -64,17 +63,45 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> {
|
||||
/// expected trait type.
|
||||
pub(super) fn check_vtable_for_type(
|
||||
&self,
|
||||
vtable_trait: Option<ty::PolyExistentialTraitRef<'tcx>>,
|
||||
expected_trait: &'tcx ty::List<ty::PolyExistentialPredicate<'tcx>>,
|
||||
vtable_dyn_type: &'tcx ty::List<ty::PolyExistentialPredicate<'tcx>>,
|
||||
expected_dyn_type: &'tcx ty::List<ty::PolyExistentialPredicate<'tcx>>,
|
||||
) -> InterpResult<'tcx> {
|
||||
let eq = match (expected_trait.principal(), vtable_trait) {
|
||||
(Some(a), Some(b)) => self.eq_in_param_env(a, b),
|
||||
(None, None) => true,
|
||||
_ => false,
|
||||
};
|
||||
if !eq {
|
||||
throw_ub!(InvalidVTableTrait { expected_trait, vtable_trait });
|
||||
// We check validity by comparing the lists of predicates for equality. We *could* instead
|
||||
// check that the dynamic type to which the vtable belongs satisfies all the expected
|
||||
// predicates, but that would likely be a lot slower and seems unnecessarily permissive.
|
||||
|
||||
// FIXME: we are skipping auto traits for now, but might revisit this in the future.
|
||||
let mut sorted_vtable: Vec<_> = vtable_dyn_type.without_auto_traits().collect();
|
||||
let mut sorted_expected: Vec<_> = expected_dyn_type.without_auto_traits().collect();
|
||||
// `skip_binder` here is okay because `stable_cmp` doesn't look at binders
|
||||
sorted_vtable.sort_by(|a, b| a.skip_binder().stable_cmp(*self.tcx, &b.skip_binder()));
|
||||
sorted_vtable.dedup();
|
||||
sorted_expected.sort_by(|a, b| a.skip_binder().stable_cmp(*self.tcx, &b.skip_binder()));
|
||||
sorted_expected.dedup();
|
||||
|
||||
if sorted_vtable.len() != sorted_expected.len() {
|
||||
throw_ub!(InvalidVTableTrait { vtable_dyn_type, expected_dyn_type });
|
||||
}
|
||||
|
||||
for (a_pred, b_pred) in std::iter::zip(sorted_vtable, sorted_expected) {
|
||||
let is_eq = match (a_pred.skip_binder(), b_pred.skip_binder()) {
|
||||
(
|
||||
ty::ExistentialPredicate::Trait(a_data),
|
||||
ty::ExistentialPredicate::Trait(b_data),
|
||||
) => self.eq_in_param_env(a_pred.rebind(a_data), b_pred.rebind(b_data)),
|
||||
|
||||
(
|
||||
ty::ExistentialPredicate::Projection(a_data),
|
||||
ty::ExistentialPredicate::Projection(b_data),
|
||||
) => self.eq_in_param_env(a_pred.rebind(a_data), b_pred.rebind(b_data)),
|
||||
|
||||
_ => false,
|
||||
};
|
||||
if !is_eq {
|
||||
throw_ub!(InvalidVTableTrait { vtable_dyn_type, expected_dyn_type });
|
||||
}
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
|
@ -452,8 +452,8 @@ impl<'rt, 'tcx, M: Machine<'tcx>> ValidityVisitor<'rt, 'tcx, M> {
|
||||
self.path,
|
||||
Ub(DanglingIntPointer{ .. } | InvalidVTablePointer(..)) =>
|
||||
InvalidVTablePtr { value: format!("{vtable}") },
|
||||
Ub(InvalidVTableTrait { expected_trait, vtable_trait }) => {
|
||||
InvalidMetaWrongTrait { expected_trait, vtable_trait: *vtable_trait }
|
||||
Ub(InvalidVTableTrait { vtable_dyn_type, expected_dyn_type }) => {
|
||||
InvalidMetaWrongTrait { vtable_dyn_type, expected_dyn_type }
|
||||
},
|
||||
);
|
||||
}
|
||||
@ -1281,8 +1281,8 @@ impl<'rt, 'tcx, M: Machine<'tcx>> ValueVisitor<'tcx, M> for ValidityVisitor<'rt,
|
||||
self.path,
|
||||
// It's not great to catch errors here, since we can't give a very good path,
|
||||
// but it's better than ICEing.
|
||||
Ub(InvalidVTableTrait { expected_trait, vtable_trait }) => {
|
||||
InvalidMetaWrongTrait { expected_trait, vtable_trait: *vtable_trait }
|
||||
Ub(InvalidVTableTrait { vtable_dyn_type, expected_dyn_type }) => {
|
||||
InvalidMetaWrongTrait { vtable_dyn_type, expected_dyn_type: *expected_dyn_type }
|
||||
},
|
||||
);
|
||||
}
|
||||
|
@ -395,8 +395,6 @@ lint_improper_ctypes_opaque = opaque types have no C equivalent
|
||||
lint_improper_ctypes_pat_help = consider using the base type instead
|
||||
|
||||
lint_improper_ctypes_pat_reason = pattern types have no C equivalent
|
||||
|
||||
lint_improper_ctypes_recursion_limit_reached = type is infinitely recursive
|
||||
lint_improper_ctypes_slice_help = consider using a raw pointer instead
|
||||
|
||||
lint_improper_ctypes_slice_reason = slices have no C equivalent
|
||||
|
@ -592,8 +592,6 @@ struct CTypesVisitorState<'tcx> {
|
||||
/// The original type being checked, before we recursed
|
||||
/// to any other types it contains.
|
||||
base_ty: Ty<'tcx>,
|
||||
/// Number of times we recursed while checking the type
|
||||
recursion_depth: usize,
|
||||
}
|
||||
|
||||
enum FfiResult<'tcx> {
|
||||
@ -899,23 +897,12 @@ impl<'a, 'tcx> ImproperCTypesVisitor<'a, 'tcx> {
|
||||
|
||||
// Protect against infinite recursion, for example
|
||||
// `struct S(*mut S);`.
|
||||
// FIXME: A recursion limit is necessary as well, for irregular
|
||||
// recursive types.
|
||||
if !acc.cache.insert(ty) {
|
||||
return FfiSafe;
|
||||
}
|
||||
|
||||
// Additional recursion check for more complex types like
|
||||
// `struct A<T> { v: *const A<A<T>>, ... }` for which the
|
||||
// cache check above won't be enough (fixes #130310)
|
||||
if !tcx.recursion_limit().value_within_limit(acc.recursion_depth) {
|
||||
return FfiUnsafe {
|
||||
ty: acc.base_ty,
|
||||
reason: fluent::lint_improper_ctypes_recursion_limit_reached,
|
||||
help: None,
|
||||
};
|
||||
}
|
||||
|
||||
acc.recursion_depth += 1;
|
||||
|
||||
match *ty.kind() {
|
||||
ty::Adt(def, args) => {
|
||||
if let Some(boxed) = ty.boxed_ty()
|
||||
@ -1261,8 +1248,7 @@ impl<'a, 'tcx> ImproperCTypesVisitor<'a, 'tcx> {
|
||||
return;
|
||||
}
|
||||
|
||||
let mut acc =
|
||||
CTypesVisitorState { cache: FxHashSet::default(), base_ty: ty, recursion_depth: 0 };
|
||||
let mut acc = CTypesVisitorState { cache: FxHashSet::default(), base_ty: ty };
|
||||
match self.check_type_for_ffi(&mut acc, ty) {
|
||||
FfiResult::FfiSafe => {}
|
||||
FfiResult::FfiPhantom(ty) => {
|
||||
|
@ -598,7 +598,10 @@ impl<'hir> Map<'hir> {
|
||||
/// in the HIR which is recorded by the map and is an item, either an item
|
||||
/// in a module, trait, or impl.
|
||||
pub fn get_parent_item(self, hir_id: HirId) -> OwnerId {
|
||||
if let Some((def_id, _node)) = self.parent_owner_iter(hir_id).next() {
|
||||
if hir_id.local_id != ItemLocalId::ZERO {
|
||||
// If this is a child of a HIR owner, return the owner.
|
||||
hir_id.owner
|
||||
} else if let Some((def_id, _node)) = self.parent_owner_iter(hir_id).next() {
|
||||
def_id
|
||||
} else {
|
||||
CRATE_OWNER_ID
|
||||
|
@ -365,8 +365,10 @@ pub enum UndefinedBehaviorInfo<'tcx> {
|
||||
InvalidVTablePointer(Pointer<AllocId>),
|
||||
/// Using a vtable for the wrong trait.
|
||||
InvalidVTableTrait {
|
||||
expected_trait: &'tcx ty::List<ty::PolyExistentialPredicate<'tcx>>,
|
||||
vtable_trait: Option<ty::PolyExistentialTraitRef<'tcx>>,
|
||||
/// The vtable that was actually referenced by the wide pointer metadata.
|
||||
vtable_dyn_type: &'tcx ty::List<ty::PolyExistentialPredicate<'tcx>>,
|
||||
/// The vtable that was expected at the point in MIR that it was accessed.
|
||||
expected_dyn_type: &'tcx ty::List<ty::PolyExistentialPredicate<'tcx>>,
|
||||
},
|
||||
/// Using a string that is not valid UTF-8,
|
||||
InvalidStr(std::str::Utf8Error),
|
||||
@ -479,8 +481,10 @@ pub enum ValidationErrorKind<'tcx> {
|
||||
value: String,
|
||||
},
|
||||
InvalidMetaWrongTrait {
|
||||
expected_trait: &'tcx ty::List<ty::PolyExistentialPredicate<'tcx>>,
|
||||
vtable_trait: Option<ty::PolyExistentialTraitRef<'tcx>>,
|
||||
/// The vtable that was actually referenced by the wide pointer metadata.
|
||||
vtable_dyn_type: &'tcx ty::List<ty::PolyExistentialPredicate<'tcx>>,
|
||||
/// The vtable that was expected at the point in MIR that it was accessed.
|
||||
expected_dyn_type: &'tcx ty::List<ty::PolyExistentialPredicate<'tcx>>,
|
||||
},
|
||||
InvalidMetaSliceTooLarge {
|
||||
ptr_kind: PointerKind,
|
||||
|
@ -232,9 +232,8 @@ impl<'s> AllocDecodingSession<'s> {
|
||||
}
|
||||
AllocDiscriminant::VTable => {
|
||||
trace!("creating vtable alloc ID");
|
||||
let ty = <Ty<'_> as Decodable<D>>::decode(decoder);
|
||||
let poly_trait_ref =
|
||||
<Option<ty::PolyExistentialTraitRef<'_>> as Decodable<D>>::decode(decoder);
|
||||
let ty = Decodable::decode(decoder);
|
||||
let poly_trait_ref = Decodable::decode(decoder);
|
||||
trace!("decoded vtable alloc instance: {ty:?}, {poly_trait_ref:?}");
|
||||
decoder.interner().reserve_and_set_vtable_alloc(ty, poly_trait_ref, CTFE_ALLOC_SALT)
|
||||
}
|
||||
@ -259,7 +258,10 @@ pub enum GlobalAlloc<'tcx> {
|
||||
/// The alloc ID is used as a function pointer.
|
||||
Function { instance: Instance<'tcx> },
|
||||
/// This alloc ID points to a symbolic (not-reified) vtable.
|
||||
VTable(Ty<'tcx>, Option<ty::PolyExistentialTraitRef<'tcx>>),
|
||||
/// We remember the full dyn type, not just the principal trait, so that
|
||||
/// const-eval and Miri can detect UB due to invalid transmutes of
|
||||
/// `dyn Trait` types.
|
||||
VTable(Ty<'tcx>, &'tcx ty::List<ty::PolyExistentialPredicate<'tcx>>),
|
||||
/// The alloc ID points to a "lazy" static variable that did not get computed (yet).
|
||||
/// This is also used to break the cycle in recursive statics.
|
||||
Static(DefId),
|
||||
@ -293,7 +295,7 @@ impl<'tcx> GlobalAlloc<'tcx> {
|
||||
#[inline]
|
||||
pub fn unwrap_vtable(&self) -> (Ty<'tcx>, Option<ty::PolyExistentialTraitRef<'tcx>>) {
|
||||
match *self {
|
||||
GlobalAlloc::VTable(ty, poly_trait_ref) => (ty, poly_trait_ref),
|
||||
GlobalAlloc::VTable(ty, dyn_ty) => (ty, dyn_ty.principal()),
|
||||
_ => bug!("expected vtable, got {:?}", self),
|
||||
}
|
||||
}
|
||||
@ -398,10 +400,10 @@ impl<'tcx> TyCtxt<'tcx> {
|
||||
pub fn reserve_and_set_vtable_alloc(
|
||||
self,
|
||||
ty: Ty<'tcx>,
|
||||
poly_trait_ref: Option<ty::PolyExistentialTraitRef<'tcx>>,
|
||||
dyn_ty: &'tcx ty::List<ty::PolyExistentialPredicate<'tcx>>,
|
||||
salt: usize,
|
||||
) -> AllocId {
|
||||
self.reserve_and_set_dedup(GlobalAlloc::VTable(ty, poly_trait_ref), salt)
|
||||
self.reserve_and_set_dedup(GlobalAlloc::VTable(ty, dyn_ty), salt)
|
||||
}
|
||||
|
||||
/// Interns the `Allocation` and return a new `AllocId`, even if there's already an identical
|
||||
|
@ -1536,11 +1536,8 @@ pub fn write_allocations<'tcx>(
|
||||
// gracefully handle it and allow buggy rustc to be debugged via allocation printing.
|
||||
None => write!(w, " (deallocated)")?,
|
||||
Some(GlobalAlloc::Function { instance, .. }) => write!(w, " (fn: {instance})")?,
|
||||
Some(GlobalAlloc::VTable(ty, Some(trait_ref))) => {
|
||||
write!(w, " (vtable: impl {trait_ref} for {ty})")?
|
||||
}
|
||||
Some(GlobalAlloc::VTable(ty, None)) => {
|
||||
write!(w, " (vtable: impl <auto trait> for {ty})")?
|
||||
Some(GlobalAlloc::VTable(ty, dyn_ty)) => {
|
||||
write!(w, " (vtable: impl {dyn_ty} for {ty})")?
|
||||
}
|
||||
Some(GlobalAlloc::Static(did)) if !tcx.is_foreign_item(did) => {
|
||||
match tcx.eval_static_initializer(did) {
|
||||
|
@ -1175,8 +1175,8 @@ fn collect_alloc<'tcx>(tcx: TyCtxt<'tcx>, alloc_id: AllocId, output: &mut MonoIt
|
||||
output.push(create_fn_mono_item(tcx, instance, DUMMY_SP));
|
||||
}
|
||||
}
|
||||
GlobalAlloc::VTable(ty, trait_ref) => {
|
||||
let alloc_id = tcx.vtable_allocation((ty, trait_ref));
|
||||
GlobalAlloc::VTable(ty, dyn_ty) => {
|
||||
let alloc_id = tcx.vtable_allocation((ty, dyn_ty.principal()));
|
||||
collect_alloc(tcx, alloc_id, output)
|
||||
}
|
||||
}
|
||||
|
@ -318,10 +318,10 @@ impl<'tcx> ReachableContext<'tcx> {
|
||||
));
|
||||
self.visit(instance.args);
|
||||
}
|
||||
GlobalAlloc::VTable(ty, trait_ref) => {
|
||||
GlobalAlloc::VTable(ty, dyn_ty) => {
|
||||
self.visit(ty);
|
||||
// Manually visit to actually see the trait's `DefId`. Type visitors won't see it
|
||||
if let Some(trait_ref) = trait_ref {
|
||||
if let Some(trait_ref) = dyn_ty.principal() {
|
||||
let ExistentialTraitRef { def_id, args } = trait_ref.skip_binder();
|
||||
self.visit_def_id(def_id, "", &"");
|
||||
self.visit(args);
|
||||
|
@ -712,8 +712,9 @@ impl<'tcx> Stable<'tcx> for mir::interpret::GlobalAlloc<'tcx> {
|
||||
mir::interpret::GlobalAlloc::Function { instance, .. } => {
|
||||
GlobalAlloc::Function(instance.stable(tables))
|
||||
}
|
||||
mir::interpret::GlobalAlloc::VTable(ty, trait_ref) => {
|
||||
GlobalAlloc::VTable(ty.stable(tables), trait_ref.stable(tables))
|
||||
mir::interpret::GlobalAlloc::VTable(ty, dyn_ty) => {
|
||||
// FIXME: Should we record the whole vtable?
|
||||
GlobalAlloc::VTable(ty.stable(tables), dyn_ty.principal().stable(tables))
|
||||
}
|
||||
mir::interpret::GlobalAlloc::Static(def) => {
|
||||
GlobalAlloc::Static(tables.static_def(*def))
|
||||
|
@ -1882,6 +1882,7 @@ supported_targets! {
|
||||
|
||||
("aarch64-unknown-linux-ohos", aarch64_unknown_linux_ohos),
|
||||
("armv7-unknown-linux-ohos", armv7_unknown_linux_ohos),
|
||||
("loongarch64-unknown-linux-ohos", loongarch64_unknown_linux_ohos),
|
||||
("x86_64-unknown-linux-ohos", x86_64_unknown_linux_ohos),
|
||||
|
||||
("x86_64-unknown-linux-none", x86_64_unknown_linux_none),
|
||||
|
@ -0,0 +1,24 @@
|
||||
use crate::spec::{Target, TargetOptions, base};
|
||||
|
||||
pub(crate) fn target() -> Target {
|
||||
Target {
|
||||
// LLVM 15 doesn't support OpenHarmony yet, use a linux target instead.
|
||||
llvm_target: "loongarch64-unknown-linux-musl".into(),
|
||||
metadata: crate::spec::TargetMetadata {
|
||||
description: Some("LoongArch64 OpenHarmony".into()),
|
||||
tier: Some(3),
|
||||
host_tools: Some(false),
|
||||
std: Some(true),
|
||||
},
|
||||
pointer_width: 64,
|
||||
data_layout: "e-m:e-p:64:64-i64:64-i128:128-n32:64-S128".into(),
|
||||
arch: "loongarch64".into(),
|
||||
options: TargetOptions {
|
||||
cpu: "generic".into(),
|
||||
features: "+f,+d".into(),
|
||||
llvm_abiname: "lp64d".into(),
|
||||
max_atomic_width: Some(64),
|
||||
..base::linux_ohos::opts()
|
||||
},
|
||||
}
|
||||
}
|
@ -3286,13 +3286,13 @@ pub const fn ptr_metadata<P: ptr::Pointee<Metadata = M> + ?Sized, M>(_ptr: *cons
|
||||
#[doc(alias = "memcpy")]
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
#[rustc_allowed_through_unstable_modules]
|
||||
#[rustc_const_unstable(feature = "const_intrinsic_copy", issue = "80697")]
|
||||
#[rustc_const_stable(feature = "const_intrinsic_copy", since = "CURRENT_RUSTC_VERSION")]
|
||||
#[inline(always)]
|
||||
#[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces
|
||||
#[rustc_diagnostic_item = "ptr_copy_nonoverlapping"]
|
||||
pub const unsafe fn copy_nonoverlapping<T>(src: *const T, dst: *mut T, count: usize) {
|
||||
extern "rust-intrinsic" {
|
||||
#[rustc_const_unstable(feature = "const_intrinsic_copy", issue = "80697")]
|
||||
#[rustc_const_stable(feature = "const_intrinsic_copy", since = "CURRENT_RUSTC_VERSION")]
|
||||
#[rustc_nounwind]
|
||||
pub fn copy_nonoverlapping<T>(src: *const T, dst: *mut T, count: usize);
|
||||
}
|
||||
@ -3388,13 +3388,13 @@ pub const unsafe fn copy_nonoverlapping<T>(src: *const T, dst: *mut T, count: us
|
||||
#[doc(alias = "memmove")]
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
#[rustc_allowed_through_unstable_modules]
|
||||
#[rustc_const_unstable(feature = "const_intrinsic_copy", issue = "80697")]
|
||||
#[rustc_const_stable(feature = "const_intrinsic_copy", since = "CURRENT_RUSTC_VERSION")]
|
||||
#[inline(always)]
|
||||
#[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces
|
||||
#[rustc_diagnostic_item = "ptr_copy"]
|
||||
pub const unsafe fn copy<T>(src: *const T, dst: *mut T, count: usize) {
|
||||
extern "rust-intrinsic" {
|
||||
#[rustc_const_unstable(feature = "const_intrinsic_copy", issue = "80697")]
|
||||
#[rustc_const_stable(feature = "const_intrinsic_copy", since = "CURRENT_RUSTC_VERSION")]
|
||||
#[rustc_nounwind]
|
||||
fn copy<T>(src: *const T, dst: *mut T, count: usize);
|
||||
}
|
||||
|
@ -128,7 +128,6 @@
|
||||
#![feature(const_hash)]
|
||||
#![feature(const_heap)]
|
||||
#![feature(const_index_range_slice_index)]
|
||||
#![feature(const_intrinsic_copy)]
|
||||
#![feature(const_intrinsic_forget)]
|
||||
#![feature(const_ipv4)]
|
||||
#![feature(const_ipv6)]
|
||||
|
@ -1192,7 +1192,7 @@ impl<T: ?Sized> *const T {
|
||||
/// See [`ptr::copy`] for safety concerns and examples.
|
||||
///
|
||||
/// [`ptr::copy`]: crate::ptr::copy()
|
||||
#[rustc_const_unstable(feature = "const_intrinsic_copy", issue = "80697")]
|
||||
#[rustc_const_stable(feature = "const_intrinsic_copy", since = "CURRENT_RUSTC_VERSION")]
|
||||
#[stable(feature = "pointer_methods", since = "1.26.0")]
|
||||
#[inline]
|
||||
#[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces
|
||||
@ -1212,7 +1212,7 @@ impl<T: ?Sized> *const T {
|
||||
/// See [`ptr::copy_nonoverlapping`] for safety concerns and examples.
|
||||
///
|
||||
/// [`ptr::copy_nonoverlapping`]: crate::ptr::copy_nonoverlapping()
|
||||
#[rustc_const_unstable(feature = "const_intrinsic_copy", issue = "80697")]
|
||||
#[rustc_const_stable(feature = "const_intrinsic_copy", since = "CURRENT_RUSTC_VERSION")]
|
||||
#[stable(feature = "pointer_methods", since = "1.26.0")]
|
||||
#[inline]
|
||||
#[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces
|
||||
|
@ -1516,11 +1516,7 @@ pub const unsafe fn read<T>(src: *const T) -> T {
|
||||
#[inline]
|
||||
#[stable(feature = "ptr_unaligned", since = "1.17.0")]
|
||||
#[rustc_const_stable(feature = "const_ptr_read", since = "1.71.0")]
|
||||
#[rustc_allow_const_fn_unstable(
|
||||
const_mut_refs,
|
||||
const_maybe_uninit_as_mut_ptr,
|
||||
const_intrinsic_copy
|
||||
)]
|
||||
#[cfg_attr(bootstrap, rustc_allow_const_fn_unstable(const_mut_refs))]
|
||||
#[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces
|
||||
#[rustc_diagnostic_item = "ptr_read_unaligned"]
|
||||
pub const unsafe fn read_unaligned<T>(src: *const T) -> T {
|
||||
|
@ -1269,7 +1269,7 @@ impl<T: ?Sized> *mut T {
|
||||
/// See [`ptr::copy`] for safety concerns and examples.
|
||||
///
|
||||
/// [`ptr::copy`]: crate::ptr::copy()
|
||||
#[rustc_const_unstable(feature = "const_intrinsic_copy", issue = "80697")]
|
||||
#[rustc_const_stable(feature = "const_intrinsic_copy", since = "CURRENT_RUSTC_VERSION")]
|
||||
#[stable(feature = "pointer_methods", since = "1.26.0")]
|
||||
#[inline(always)]
|
||||
#[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces
|
||||
@ -1289,7 +1289,7 @@ impl<T: ?Sized> *mut T {
|
||||
/// See [`ptr::copy_nonoverlapping`] for safety concerns and examples.
|
||||
///
|
||||
/// [`ptr::copy_nonoverlapping`]: crate::ptr::copy_nonoverlapping()
|
||||
#[rustc_const_unstable(feature = "const_intrinsic_copy", issue = "80697")]
|
||||
#[rustc_const_stable(feature = "const_intrinsic_copy", since = "CURRENT_RUSTC_VERSION")]
|
||||
#[stable(feature = "pointer_methods", since = "1.26.0")]
|
||||
#[inline(always)]
|
||||
#[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces
|
||||
@ -1309,7 +1309,7 @@ impl<T: ?Sized> *mut T {
|
||||
/// See [`ptr::copy`] for safety concerns and examples.
|
||||
///
|
||||
/// [`ptr::copy`]: crate::ptr::copy()
|
||||
#[rustc_const_unstable(feature = "const_intrinsic_copy", issue = "80697")]
|
||||
#[rustc_const_stable(feature = "const_intrinsic_copy", since = "CURRENT_RUSTC_VERSION")]
|
||||
#[stable(feature = "pointer_methods", since = "1.26.0")]
|
||||
#[inline(always)]
|
||||
#[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces
|
||||
@ -1329,7 +1329,7 @@ impl<T: ?Sized> *mut T {
|
||||
/// See [`ptr::copy_nonoverlapping`] for safety concerns and examples.
|
||||
///
|
||||
/// [`ptr::copy_nonoverlapping`]: crate::ptr::copy_nonoverlapping()
|
||||
#[rustc_const_unstable(feature = "const_intrinsic_copy", issue = "80697")]
|
||||
#[rustc_const_stable(feature = "const_intrinsic_copy", since = "CURRENT_RUSTC_VERSION")]
|
||||
#[stable(feature = "pointer_methods", since = "1.26.0")]
|
||||
#[inline(always)]
|
||||
#[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces
|
||||
|
@ -924,7 +924,7 @@ impl<T: ?Sized> NonNull<T> {
|
||||
#[inline(always)]
|
||||
#[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces
|
||||
#[stable(feature = "non_null_convenience", since = "1.80.0")]
|
||||
#[rustc_const_unstable(feature = "const_intrinsic_copy", issue = "80697")]
|
||||
#[rustc_const_stable(feature = "const_intrinsic_copy", since = "CURRENT_RUSTC_VERSION")]
|
||||
pub const unsafe fn copy_to(self, dest: NonNull<T>, count: usize)
|
||||
where
|
||||
T: Sized,
|
||||
@ -944,7 +944,7 @@ impl<T: ?Sized> NonNull<T> {
|
||||
#[inline(always)]
|
||||
#[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces
|
||||
#[stable(feature = "non_null_convenience", since = "1.80.0")]
|
||||
#[rustc_const_unstable(feature = "const_intrinsic_copy", issue = "80697")]
|
||||
#[rustc_const_stable(feature = "const_intrinsic_copy", since = "CURRENT_RUSTC_VERSION")]
|
||||
pub const unsafe fn copy_to_nonoverlapping(self, dest: NonNull<T>, count: usize)
|
||||
where
|
||||
T: Sized,
|
||||
@ -964,7 +964,7 @@ impl<T: ?Sized> NonNull<T> {
|
||||
#[inline(always)]
|
||||
#[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces
|
||||
#[stable(feature = "non_null_convenience", since = "1.80.0")]
|
||||
#[rustc_const_unstable(feature = "const_intrinsic_copy", issue = "80697")]
|
||||
#[rustc_const_stable(feature = "const_intrinsic_copy", since = "CURRENT_RUSTC_VERSION")]
|
||||
pub const unsafe fn copy_from(self, src: NonNull<T>, count: usize)
|
||||
where
|
||||
T: Sized,
|
||||
@ -984,7 +984,7 @@ impl<T: ?Sized> NonNull<T> {
|
||||
#[inline(always)]
|
||||
#[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces
|
||||
#[stable(feature = "non_null_convenience", since = "1.80.0")]
|
||||
#[rustc_const_unstable(feature = "const_intrinsic_copy", issue = "80697")]
|
||||
#[rustc_const_stable(feature = "const_intrinsic_copy", since = "CURRENT_RUSTC_VERSION")]
|
||||
pub const unsafe fn copy_from_nonoverlapping(self, src: NonNull<T>, count: usize)
|
||||
where
|
||||
T: Sized,
|
||||
|
@ -21,7 +21,6 @@
|
||||
#![feature(const_cell_into_inner)]
|
||||
#![feature(const_hash)]
|
||||
#![feature(const_heap)]
|
||||
#![feature(const_intrinsic_copy)]
|
||||
#![feature(const_ip)]
|
||||
#![feature(const_ipv4)]
|
||||
#![feature(const_ipv6)]
|
||||
|
@ -1,8 +1,6 @@
|
||||
#![no_std]
|
||||
#![feature(
|
||||
const_intrinsic_copy,
|
||||
const_refs_to_cell,
|
||||
const_maybe_uninit_as_mut_ptr,
|
||||
const_mut_refs,
|
||||
convert_float_to_int,
|
||||
core_intrinsics,
|
||||
|
@ -32,13 +32,17 @@
|
||||
//!
|
||||
//! Once you are familiar with the contents of the standard library you may
|
||||
//! begin to find the verbosity of the prose distracting. At this stage in your
|
||||
//! development you may want to press the `[-]` button near the top of the
|
||||
//! page to collapse it into a more skimmable view.
|
||||
//! development you may want to press the <code>
|
||||
//! <svg style="width:0.75rem;height:0.75rem" viewBox="0 0 12 12"
|
||||
//! stroke="currentColor" fill="none">
|
||||
//! <path d="M2,2l4,4l4,-4M2,6l4,4l4,-4"/></svg> Summary</code> button near the
|
||||
//! top of the page to collapse it into a more skimmable view.
|
||||
//!
|
||||
//! While you are looking at that `[-]` button also notice the `source`
|
||||
//! link. Rust's API documentation comes with the source code and you are
|
||||
//! encouraged to read it. The standard library source is generally high
|
||||
//! quality and a peek behind the curtains is often enlightening.
|
||||
//! While you are looking at the top of the page, also notice the
|
||||
//! <code>source</code> link. Rust's API documentation comes with the source
|
||||
//! code and you are encouraged to read it. The standard library source is
|
||||
//! generally high quality and a peek behind the curtains is
|
||||
//! often enlightening.
|
||||
//!
|
||||
//! # What is in the standard library documentation?
|
||||
//!
|
||||
|
@ -1 +1 @@
|
||||
Subproject commit e7d217be2a75ef1753f0988d6ccaba4d7e376259
|
||||
Subproject commit 99cf75a5414fa8adbe3974bd0836661ca901708f
|
@ -1 +1 @@
|
||||
Subproject commit b3ca7ade0f87d7e3fb538776defc5b2cc4188172
|
||||
Subproject commit c7ebae25cb4801a31b6f05353f6d85bfa6feedd1
|
@ -1 +1 @@
|
||||
Subproject commit 687faf9958c52116d003b41dfd29cc1cf44f5311
|
||||
Subproject commit 24fb2687cdbc54fa18ae4acf5d879cfceca77b2c
|
@ -1 +1 @@
|
||||
Subproject commit 0ed9229f5b6f7824b333beabd7e3d5ba4b9bd971
|
||||
Subproject commit 555f3de2fa0d61c4294b74d245f1cbad6fcbf589
|
@ -313,6 +313,7 @@ target | std | host | notes
|
||||
`i686-uwp-windows-msvc` | ✓ | | [^x86_32-floats-return-ABI]
|
||||
[`i686-win7-windows-msvc`](platform-support/win7-windows-msvc.md) | ✓ | | 32-bit Windows 7 support [^x86_32-floats-return-ABI]
|
||||
[`i686-wrs-vxworks`](platform-support/vxworks.md) | ✓ | | [^x86_32-floats-return-ABI]
|
||||
[`loongarch64-unknown-linux-ohos`](platform-support/openharmony.md) | ✓ | | LoongArch64 OpenHarmony
|
||||
[`m68k-unknown-linux-gnu`](platform-support/m68k-unknown-linux-gnu.md) | ? | | Motorola 680x0 Linux
|
||||
`mips-unknown-linux-gnu` | ✓ | ✓ | MIPS Linux (kernel 4.4, glibc 2.23)
|
||||
`mips-unknown-linux-musl` | ✓ | | MIPS Linux with musl 1.2.3
|
||||
|
@ -2,6 +2,14 @@
|
||||
|
||||
**Tier: 2**
|
||||
|
||||
* aarch64-unknown-linux-ohos
|
||||
* armv7-unknown-linux-ohos
|
||||
* x86_64-unknown-linux-ohos
|
||||
|
||||
**Tier: 3**
|
||||
|
||||
* loongarch64-unknown-linux-ohos
|
||||
|
||||
Targets for the [OpenHarmony](https://gitee.com/openharmony/docs/) operating
|
||||
system.
|
||||
|
||||
|
@ -26,8 +26,11 @@ pub(crate) fn render(cx: &mut Context<'_>, krate: &clean::Crate) -> Result<(), E
|
||||
|
||||
let dst = cx.dst.join("src").join(krate.name(cx.tcx()).as_str());
|
||||
cx.shared.ensure_dir(&dst)?;
|
||||
let crate_name = krate.name(cx.tcx());
|
||||
let crate_name = crate_name.as_str();
|
||||
|
||||
let mut collector = SourceCollector { dst, cx, emitted_local_sources: FxHashSet::default() };
|
||||
let mut collector =
|
||||
SourceCollector { dst, cx, emitted_local_sources: FxHashSet::default(), crate_name };
|
||||
collector.visit_crate(krate);
|
||||
Ok(())
|
||||
}
|
||||
@ -115,6 +118,8 @@ struct SourceCollector<'a, 'tcx> {
|
||||
/// Root destination to place all HTML output into
|
||||
dst: PathBuf,
|
||||
emitted_local_sources: FxHashSet<PathBuf>,
|
||||
|
||||
crate_name: &'a str,
|
||||
}
|
||||
|
||||
impl DocVisitor for SourceCollector<'_, '_> {
|
||||
@ -210,6 +215,9 @@ impl SourceCollector<'_, '_> {
|
||||
},
|
||||
);
|
||||
|
||||
let src_fname = p.file_name().expect("source has no filename").to_os_string();
|
||||
let mut fname = src_fname.clone();
|
||||
|
||||
let root_path = PathBuf::from("../../").join(root_path.into_inner());
|
||||
let mut root_path = root_path.to_string_lossy();
|
||||
if let Some(c) = root_path.as_bytes().last()
|
||||
@ -217,12 +225,12 @@ impl SourceCollector<'_, '_> {
|
||||
{
|
||||
root_path += "/";
|
||||
}
|
||||
let mut file_path = Path::new(&self.crate_name).join(&*cur.borrow());
|
||||
file_path.push(&fname);
|
||||
fname.push(".html");
|
||||
let mut cur = self.dst.join(cur.into_inner());
|
||||
shared.ensure_dir(&cur)?;
|
||||
|
||||
let src_fname = p.file_name().expect("source has no filename").to_os_string();
|
||||
let mut fname = src_fname.clone();
|
||||
fname.push(".html");
|
||||
cur.push(&fname);
|
||||
|
||||
let title = format!("{} - source", src_fname.to_string_lossy());
|
||||
@ -250,7 +258,7 @@ impl SourceCollector<'_, '_> {
|
||||
cx,
|
||||
&root_path,
|
||||
highlight::DecorationInfo::default(),
|
||||
SourceContext::Standalone,
|
||||
SourceContext::Standalone { file_path },
|
||||
)
|
||||
},
|
||||
&shared.style_files,
|
||||
@ -312,10 +320,11 @@ struct ScrapedSource<'a, Code: std::fmt::Display> {
|
||||
struct Source<Code: std::fmt::Display> {
|
||||
lines: RangeInclusive<usize>,
|
||||
code_html: Code,
|
||||
file_path: Option<(String, String)>,
|
||||
}
|
||||
|
||||
pub(crate) enum SourceContext<'a> {
|
||||
Standalone,
|
||||
Standalone { file_path: PathBuf },
|
||||
Embedded(ScrapedInfo<'a>),
|
||||
}
|
||||
|
||||
@ -344,9 +353,19 @@ pub(crate) fn print_src(
|
||||
});
|
||||
let lines = s.lines().count();
|
||||
match source_context {
|
||||
SourceContext::Standalone => {
|
||||
Source { lines: (1..=lines), code_html: code }.render_into(&mut writer).unwrap()
|
||||
SourceContext::Standalone { file_path } => Source {
|
||||
lines: (1..=lines),
|
||||
code_html: code,
|
||||
file_path: if let Some(file_name) = file_path.file_name()
|
||||
&& let Some(file_path) = file_path.parent()
|
||||
{
|
||||
Some((file_path.display().to_string(), file_name.display().to_string()))
|
||||
} else {
|
||||
None
|
||||
},
|
||||
}
|
||||
.render_into(&mut writer)
|
||||
.unwrap(),
|
||||
SourceContext::Embedded(info) => {
|
||||
let lines = (1 + info.offset)..=(lines + info.offset);
|
||||
ScrapedSource { info, lines, code_html: code }.render_into(&mut writer).unwrap();
|
||||
|
@ -61,6 +61,8 @@ nav.sub {
|
||||
--copy-path-img-hover-filter: invert(35%);
|
||||
--code-example-button-color: #7f7f7f;
|
||||
--code-example-button-hover-color: #595959;
|
||||
--settings-menu-filter: invert(50%);
|
||||
--settings-menu-hover-filter: invert(35%);
|
||||
--codeblock-error-hover-color: rgb(255, 0, 0);
|
||||
--codeblock-error-color: rgba(255, 0, 0, .5);
|
||||
--codeblock-ignore-hover-color: rgb(255, 142, 0);
|
||||
@ -87,7 +89,6 @@ nav.sub {
|
||||
--search-tab-button-not-selected-background: #e6e6e6;
|
||||
--search-tab-button-selected-border-top-color: #0089ff;
|
||||
--search-tab-button-selected-background: #fff;
|
||||
--settings-menu-filter: none;
|
||||
--stab-background-color: #fff5d6;
|
||||
--stab-code-color: #000;
|
||||
--code-highlight-kw-color: #8959a8;
|
||||
@ -192,6 +193,8 @@ nav.sub {
|
||||
--search-tab-button-not-selected-background: #252525;
|
||||
--search-tab-button-selected-border-top-color: #0089ff;
|
||||
--search-tab-button-selected-background: #353535;
|
||||
--settings-menu-filter: invert(50%);
|
||||
--settings-menu-hover-filter: invert(65%);
|
||||
--stab-background-color: #314559;
|
||||
--stab-code-color: #e6e1cf;
|
||||
--code-highlight-kw-color: #ab8ac1;
|
||||
|
@ -34,6 +34,8 @@ xmlns="http://www.w3.org/2000/svg" fill="black" height="18px">\
|
||||
</g></svg>');
|
||||
--button-left-margin: 4px;
|
||||
--button-border-radius: 2px;
|
||||
--toolbar-button-border-radius: 6px;
|
||||
--code-block-border-radius: 6px;
|
||||
}
|
||||
|
||||
/* See FiraSans-LICENSE.txt for the Fira Sans license. */
|
||||
@ -165,7 +167,7 @@ h1, h2, h3, h4 {
|
||||
.main-heading h1 {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
flex-grow: 1;
|
||||
grid-area: main-heading-h1;
|
||||
/* We use overflow-wrap: break-word for Safari, which doesn't recognize
|
||||
`anywhere`: https://developer.mozilla.org/en-US/docs/Web/CSS/overflow-wrap */
|
||||
overflow-wrap: break-word;
|
||||
@ -174,10 +176,28 @@ h1, h2, h3, h4 {
|
||||
overflow-wrap: anywhere;
|
||||
}
|
||||
.main-heading {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
position: relative;
|
||||
display: grid;
|
||||
grid-template-areas:
|
||||
"main-heading-breadcrumbs main-heading-breadcrumbs"
|
||||
"main-heading-h1 main-heading-toolbar"
|
||||
"main-heading-sub-heading main-heading-toolbar";
|
||||
grid-template-columns: 1fr max-content;
|
||||
grid-template-rows: 25px min-content min-content;
|
||||
padding-bottom: 6px;
|
||||
margin-bottom: 15px;
|
||||
margin-bottom: 11px;
|
||||
}
|
||||
.rustdoc-breadcrumbs {
|
||||
grid-area: main-heading-breadcrumbs;
|
||||
height: 25px;
|
||||
line-height: 1.25;
|
||||
display: flex;
|
||||
align-items: end;
|
||||
}
|
||||
.rustdoc-breadcrumbs a {
|
||||
padding: 4px 0;
|
||||
margin: -4px 0;
|
||||
z-index: 1;
|
||||
}
|
||||
/* The only headings that get underlines are:
|
||||
Markdown-generated headings within the top-doc
|
||||
@ -218,11 +238,13 @@ h1, h2, h3, h4, h5, h6,
|
||||
.search-results .result-name,
|
||||
.item-name > a,
|
||||
.out-of-band,
|
||||
.sub-heading,
|
||||
span.since,
|
||||
a.src,
|
||||
#help-button > a,
|
||||
rustdoc-toolbar,
|
||||
summary.hideme,
|
||||
.scraped-example-list,
|
||||
.rustdoc-breadcrumbs,
|
||||
/* This selector is for the items listed in the "all items" page. */
|
||||
ul.all-items {
|
||||
font-family: "Fira Sans", Arial, NanumBarunGothic, sans-serif;
|
||||
@ -891,14 +913,27 @@ both the code example and the line numbers, so we need to remove the radius in t
|
||||
overflow-x: auto;
|
||||
}
|
||||
|
||||
.out-of-band {
|
||||
.sub-heading {
|
||||
font-size: 1rem;
|
||||
flex-grow: 0;
|
||||
font-size: 1.125rem;
|
||||
grid-area: main-heading-sub-heading;
|
||||
line-height: 1.25;
|
||||
padding-bottom: 4px;
|
||||
}
|
||||
|
||||
.main-heading rustdoc-toolbar, .main-heading .out-of-band {
|
||||
grid-area: main-heading-toolbar;
|
||||
}
|
||||
rustdoc-toolbar {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
flex-wrap: nowrap;
|
||||
}
|
||||
|
||||
.docblock code, .docblock-short code,
|
||||
pre, .rustdoc.src .example-wrap, .example-wrap .src-line-numbers {
|
||||
background-color: var(--code-block-background-color);
|
||||
border-radius: var(--code-block-border-radius);
|
||||
}
|
||||
|
||||
#main-content {
|
||||
@ -945,7 +980,7 @@ div.where {
|
||||
nav.sub {
|
||||
flex-grow: 1;
|
||||
flex-flow: row nowrap;
|
||||
margin: 4px 0 25px 0;
|
||||
margin: 4px 0 0 0;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
}
|
||||
@ -956,7 +991,7 @@ nav.sub {
|
||||
flex-grow: 1;
|
||||
}
|
||||
.src nav.sub {
|
||||
margin: 0 0 15px 0;
|
||||
margin: 0 0 -10px 0;
|
||||
}
|
||||
|
||||
.section-header {
|
||||
@ -1066,6 +1101,11 @@ table,
|
||||
with boxes (i.e. from the flex layout) */
|
||||
align-items: baseline;
|
||||
}
|
||||
.search-results-title + .sub-heading {
|
||||
color: var(--main-color);
|
||||
display: flex;
|
||||
align-items: center;
|
||||
}
|
||||
#crate-search-div {
|
||||
/* ensures that 100% in properties of #crate-search-div:after
|
||||
are relative to the size of this div */
|
||||
@ -1289,10 +1329,16 @@ so that we can apply CSS-filters to change the arrow color in themes */
|
||||
border-color: var(--settings-input-color) !important;
|
||||
}
|
||||
|
||||
#settings.popover {
|
||||
--popover-arrow-offset: 202px;
|
||||
top: calc(100% - 16px);
|
||||
}
|
||||
|
||||
/* use larger max-width for help popover, but not for help.html */
|
||||
#help.popover {
|
||||
max-width: 600px;
|
||||
--popover-arrow-offset: 48px;
|
||||
--popover-arrow-offset: 118px;
|
||||
top: calc(100% - 16px);
|
||||
}
|
||||
|
||||
#help dt {
|
||||
@ -1300,10 +1346,15 @@ so that we can apply CSS-filters to change the arrow color in themes */
|
||||
clear: left;
|
||||
margin-right: 0.5rem;
|
||||
}
|
||||
#help dd {
|
||||
margin-bottom: 0.5rem;
|
||||
}
|
||||
#help span.top, #help span.bottom {
|
||||
text-align: center;
|
||||
display: block;
|
||||
font-size: 1.125rem;
|
||||
padding: 0 0.5rem;
|
||||
text-wrap-style: balance;
|
||||
}
|
||||
#help span.top {
|
||||
margin: 10px 0;
|
||||
@ -1315,10 +1366,13 @@ so that we can apply CSS-filters to change the arrow color in themes */
|
||||
clear: both;
|
||||
border-top: 1px solid var(--border-color);
|
||||
}
|
||||
.side-by-side {
|
||||
display: flex;
|
||||
margin-bottom: 20px;
|
||||
}
|
||||
.side-by-side > div {
|
||||
width: 50%;
|
||||
float: left;
|
||||
padding: 0 20px 20px 17px;
|
||||
padding: 0 20px 0 17px;
|
||||
}
|
||||
|
||||
.item-info .stab {
|
||||
@ -1381,7 +1435,9 @@ so that we can apply CSS-filters to change the arrow color in themes */
|
||||
}
|
||||
|
||||
.rightside:not(a),
|
||||
.out-of-band {
|
||||
.out-of-band,
|
||||
.sub-heading,
|
||||
rustdoc-toolbar {
|
||||
color: var(--right-side-color);
|
||||
}
|
||||
|
||||
@ -1595,8 +1651,8 @@ instead, we check that it's not a "finger" cursor.
|
||||
display: block;
|
||||
}
|
||||
|
||||
.out-of-band > span.since {
|
||||
font-size: 1.25rem;
|
||||
.main-heading span.since::before {
|
||||
content: "Since ";
|
||||
}
|
||||
|
||||
.sub-variant h4 {
|
||||
@ -1698,6 +1754,7 @@ a.tooltip:hover::after {
|
||||
}
|
||||
|
||||
#search-tabs {
|
||||
margin-top: 0.25rem;
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
gap: 1px;
|
||||
@ -1759,9 +1816,10 @@ a.tooltip:hover::after {
|
||||
border-bottom: 1px solid var(--border-color);
|
||||
}
|
||||
|
||||
#settings-menu, #help-button {
|
||||
#settings-menu, #help-button, button#toggle-all-docs {
|
||||
margin-left: var(--button-left-margin);
|
||||
display: flex;
|
||||
line-height: 1.25;
|
||||
}
|
||||
#sidebar-button {
|
||||
display: none;
|
||||
@ -1785,33 +1843,36 @@ a.tooltip:hover::after {
|
||||
.hide-sidebar .src #sidebar-button {
|
||||
position: static;
|
||||
}
|
||||
#settings-menu > a, #help-button > a, #sidebar-button > a {
|
||||
#settings-menu > a, #help-button > a, #sidebar-button > a, button#toggle-all-docs {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
background-color: var(--button-background-color);
|
||||
border: 1px solid var(--border-color);
|
||||
flex-direction: column;
|
||||
border: 1px solid transparent;
|
||||
border-radius: var(--button-border-radius);
|
||||
color: var(--settings-button-color);
|
||||
/* Rare exception to specifying font sizes in rem. Since this is acting
|
||||
as an icon, it's okay to specify their sizes in pixels. */
|
||||
font-size: 20px;
|
||||
color: var(--main-color);
|
||||
}
|
||||
#settings-menu > a, #help-button > a, button#toggle-all-docs {
|
||||
width: 80px;
|
||||
border-radius: var(--toolbar-button-border-radius);
|
||||
}
|
||||
#sidebar-button > a {
|
||||
background-color: var(--button-background-color);
|
||||
border-color: var(--border-color);
|
||||
width: 33px;
|
||||
}
|
||||
|
||||
#settings-menu > a:hover, #settings-menu > a:focus,
|
||||
#help-button > a:hover, #help-button > a:focus,
|
||||
#sidebar-button > a:hover, #sidebar-button > a:focus {
|
||||
#settings-menu > a:hover, #settings-menu > a:focus-visible,
|
||||
#help-button > a:hover, #help-button > a:focus-visible,
|
||||
#sidebar-button > a:hover, #sidebar-button > a:focus-visible,
|
||||
button#toggle-all-docs:hover, button#toggle-all-docs:focus-visible {
|
||||
border-color: var(--settings-button-border-focus);
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
#settings-menu > a {
|
||||
line-height: 0;
|
||||
font-size: 0;
|
||||
}
|
||||
#settings-menu > a:before {
|
||||
/* Wheel <https://www.svgrepo.com/svg/384069/settings-cog-gear> */
|
||||
content: url('data:image/svg+xml,<svg width="22" height="22" viewBox="0 0 12 12" \
|
||||
content: url('data:image/svg+xml,<svg width="18" height="18" viewBox="0 0 12 12" \
|
||||
enable-background="new 0 0 12 12" xmlns="http://www.w3.org/2000/svg">\
|
||||
<path d="M10.25,6c0-0.1243286-0.0261841-0.241333-0.0366211-0.362915l1.6077881-1.5545654l\
|
||||
-1.25-2.1650391 c0,0-1.2674561,0.3625488-2.1323853,0.6099854c-0.2034912-0.1431885-0.421875\
|
||||
@ -1824,16 +1885,70 @@ a.tooltip:hover::after {
|
||||
-0.3701782l2.1323853,0.6099854l1.25-2.1650391L10.2133789,6.362915 C10.2238159,6.241333,\
|
||||
10.25,6.1243286,10.25,6z M6,7.5C5.1715698,7.5,4.5,6.8284302,4.5,6S5.1715698,4.5,6,4.5S7.5\
|
||||
,5.1715698,7.5,6 S6.8284302,7.5,6,7.5z" fill="black"/></svg>');
|
||||
width: 22px;
|
||||
height: 22px;
|
||||
width: 18px;
|
||||
height: 18px;
|
||||
filter: var(--settings-menu-filter);
|
||||
}
|
||||
|
||||
button#toggle-all-docs:before {
|
||||
/* Custom arrow icon */
|
||||
content: url('data:image/svg+xml,<svg width="18" height="18" viewBox="0 0 12 12" \
|
||||
enable-background="new 0 0 12 12" xmlns="http://www.w3.org/2000/svg">\
|
||||
<path d="M2,2l4,4l4,-4M2,6l4,4l4,-4" stroke="black" fill="none" stroke-width="2px"/></svg>');
|
||||
width: 18px;
|
||||
height: 18px;
|
||||
filter: var(--settings-menu-filter);
|
||||
}
|
||||
|
||||
#help-button > a:before {
|
||||
/* Question mark with circle */
|
||||
content: url('data:image/svg+xml,<svg width="18" height="18" viewBox="0 0 12 12" \
|
||||
enable-background="new 0 0 12 12" xmlns="http://www.w3.org/2000/svg" fill="none">\
|
||||
<circle r="5.25" cx="6" cy="6" stroke-width="1.25" stroke="black"/>\
|
||||
<text x="6" y="7" style="font:8px sans-serif;font-weight:1000" text-anchor="middle" \
|
||||
dominant-baseline="middle" fill="black">?</text></svg>');
|
||||
width: 18px;
|
||||
height: 18px;
|
||||
filter: var(--settings-menu-filter);
|
||||
}
|
||||
|
||||
button#toggle-all-docs:before,
|
||||
#help-button > a:before,
|
||||
#settings-menu > a:before {
|
||||
filter: var(--settings-menu-filter);
|
||||
margin: 8px;
|
||||
}
|
||||
|
||||
@media not (pointer: coarse) {
|
||||
button#toggle-all-docs:hover:before,
|
||||
#help-button > a:hover:before,
|
||||
#settings-menu > a:hover:before {
|
||||
filter: var(--settings-menu-hover-filter);
|
||||
}
|
||||
}
|
||||
|
||||
button[disabled]#toggle-all-docs {
|
||||
opacity: 0.25;
|
||||
border: solid 1px var(--main-background-color);
|
||||
background-size: cover;
|
||||
}
|
||||
|
||||
button[disabled]#toggle-all-docs:hover {
|
||||
border: solid 1px var(--main-background-color);
|
||||
cursor: not-allowed;
|
||||
}
|
||||
|
||||
rustdoc-toolbar span.label {
|
||||
font-size: 1rem;
|
||||
flex-grow: 1;
|
||||
padding-bottom: 4px;
|
||||
}
|
||||
|
||||
#sidebar-button > a:before {
|
||||
/* sidebar resizer image */
|
||||
content: url('data:image/svg+xml,<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 22 22" \
|
||||
fill="none" stroke="black">\
|
||||
<rect x="1" y="1" width="20" height="20" ry="1.5" stroke-width="1.5"/>\
|
||||
<rect x="1" y="1" width="20" height="20" ry="1.5" stroke-width="1.5" stroke="%23777"/>\
|
||||
<circle cx="4.375" cy="4.375" r="1" stroke-width=".75"/>\
|
||||
<path d="m7.6121 3v16 M5.375 7.625h-2 m2 3h-2 m2 3h-2" stroke-width="1.25"/></svg>');
|
||||
width: 22px;
|
||||
@ -1948,10 +2063,10 @@ details.toggle > summary.hideme > span {
|
||||
}
|
||||
|
||||
details.toggle > summary::before {
|
||||
/* toggle plus */
|
||||
background: url('data:image/svg+xml,<svg width="17" height="17" \
|
||||
shape-rendering="crispEdges" stroke="black" fill="none" xmlns="http://www.w3.org/2000/svg"><path \
|
||||
d="M5 2.5H2.5v12H5m7-12h2.5v12H12M5 8.5h7M8.5 12V8.625v0V5"/></svg>') no-repeat top left;
|
||||
/* arrow pointing left */
|
||||
background: url('data:image/svg+xml,<svg width="16" height="16" viewBox="0 0 12 12" \
|
||||
enable-background="new 0 0 12 12" xmlns="http://www.w3.org/2000/svg">\
|
||||
<path d="M4,2l4,4l-4,4" stroke="black" fill="none" stroke-width="1px"/></svg>');
|
||||
content: "";
|
||||
cursor: pointer;
|
||||
width: 16px;
|
||||
@ -2034,10 +2149,10 @@ details.toggle[open] > summary.hideme > span {
|
||||
}
|
||||
|
||||
details.toggle[open] > summary::before {
|
||||
/* toggle minus */
|
||||
background: url('data:image/svg+xml,<svg width="17" height="17" \
|
||||
shape-rendering="crispEdges" stroke="black" fill="none" xmlns="http://www.w3.org/2000/svg"><path \
|
||||
d="M5 2.5H2.5v12H5m7-12h2.5v12H12M5 8.5h7"/></svg>') no-repeat top left;
|
||||
/* arrow pointing down */
|
||||
background: url('data:image/svg+xml,<svg width="16" height="16" viewBox="0 0 12 12" \
|
||||
enable-background="new 0 0 12 12" xmlns="http://www.w3.org/2000/svg">\
|
||||
<path d="M2,4l4,4l4,-4" stroke="black" fill="none" stroke-width="1px"/></svg>');
|
||||
}
|
||||
|
||||
details.toggle[open] > summary::after {
|
||||
@ -2090,6 +2205,12 @@ However, it's not needed with smaller screen width because the doc/code block is
|
||||
#search-tabs .count {
|
||||
display: block;
|
||||
}
|
||||
.side-by-side {
|
||||
flex-direction: column-reverse;
|
||||
}
|
||||
.side-by-side > div {
|
||||
width: auto;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
@ -2106,6 +2227,25 @@ in src-script.js and main.js
|
||||
scroll-margin-top: 45px;
|
||||
}
|
||||
|
||||
/* We don't display this button on mobile devices. */
|
||||
#copy-path {
|
||||
display: none;
|
||||
}
|
||||
|
||||
/* Text label takes up too much space at this size. */
|
||||
rustdoc-toolbar span.label {
|
||||
display: none;
|
||||
}
|
||||
#settings-menu > a, #help-button > a, button#toggle-all-docs {
|
||||
width: 33px;
|
||||
}
|
||||
#settings.popover {
|
||||
--popover-arrow-offset: 86px;
|
||||
}
|
||||
#help.popover {
|
||||
--popover-arrow-offset: 48px;
|
||||
}
|
||||
|
||||
.rustdoc {
|
||||
/* Sidebar should overlay main content, rather than pushing main content to the right.
|
||||
Turn off `display: flex` on the body element. */
|
||||
@ -2117,20 +2257,6 @@ in src-script.js and main.js
|
||||
padding-top: 0px;
|
||||
}
|
||||
|
||||
.main-heading {
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
.out-of-band {
|
||||
text-align: left;
|
||||
margin-left: initial;
|
||||
padding: initial;
|
||||
}
|
||||
|
||||
.out-of-band .since::before {
|
||||
content: "Since ";
|
||||
}
|
||||
|
||||
/* Hide the logo and item name from the sidebar. Those are displayed
|
||||
in the mobile-topbar instead. */
|
||||
.sidebar .logo-container,
|
||||
@ -2163,6 +2289,9 @@ in src-script.js and main.js
|
||||
.src .search-form {
|
||||
margin-left: 40px;
|
||||
}
|
||||
.src .main-heading {
|
||||
margin-left: 8px;
|
||||
}
|
||||
.hide-sidebar .search-form {
|
||||
margin-left: 32px;
|
||||
}
|
||||
@ -2234,16 +2363,11 @@ in src-script.js and main.js
|
||||
left: -11px;
|
||||
}
|
||||
|
||||
/* We don't display these buttons on mobile devices. */
|
||||
#copy-path, #help-button {
|
||||
display: none;
|
||||
}
|
||||
|
||||
/* sidebar button becomes topbar button */
|
||||
#sidebar-button > a:before {
|
||||
content: url('data:image/svg+xml,<svg xmlns="http://www.w3.org/2000/svg" \
|
||||
viewBox="0 0 22 22" fill="none" stroke="black">\
|
||||
<rect x="1" y="1" width="20" height="20" ry="1.5" stroke-width="1.5"/>\
|
||||
<rect x="1" y="1" width="20" height="20" ry="1.5" stroke-width="1.5" stroke="%23777"/>\
|
||||
<circle cx="4.375" cy="4.375" r="1" stroke-width=".75"/>\
|
||||
<path d="m3 7.375h16m0-3h-4" stroke-width="1.25"/></svg>');
|
||||
width: 22px;
|
||||
@ -2305,7 +2429,7 @@ in src-script.js and main.js
|
||||
}
|
||||
|
||||
.src nav.sub {
|
||||
margin: 0;
|
||||
margin: 0 0 -25px 0;
|
||||
padding: var(--nav-sub-mobile-padding);
|
||||
}
|
||||
}
|
||||
@ -2543,6 +2667,8 @@ by default.
|
||||
--copy-path-img-hover-filter: invert(35%);
|
||||
--code-example-button-color: #7f7f7f;
|
||||
--code-example-button-hover-color: #595959;
|
||||
--settings-menu-filter: invert(50%);
|
||||
--settings-menu-hover-filter: invert(35%);
|
||||
--codeblock-error-hover-color: rgb(255, 0, 0);
|
||||
--codeblock-error-color: rgba(255, 0, 0, .5);
|
||||
--codeblock-ignore-hover-color: rgb(255, 142, 0);
|
||||
@ -2569,7 +2695,6 @@ by default.
|
||||
--search-tab-button-not-selected-background: #e6e6e6;
|
||||
--search-tab-button-selected-border-top-color: #0089ff;
|
||||
--search-tab-button-selected-background: #fff;
|
||||
--settings-menu-filter: none;
|
||||
--stab-background-color: #fff5d6;
|
||||
--stab-code-color: #000;
|
||||
--code-highlight-kw-color: #8959a8;
|
||||
@ -2673,7 +2798,8 @@ by default.
|
||||
--search-tab-button-not-selected-background: #252525;
|
||||
--search-tab-button-selected-border-top-color: #0089ff;
|
||||
--search-tab-button-selected-background: #353535;
|
||||
--settings-menu-filter: none;
|
||||
--settings-menu-filter: invert(50%);
|
||||
--settings-menu-hover-filter: invert(65%);
|
||||
--stab-background-color: #314559;
|
||||
--stab-code-color: #e6e1cf;
|
||||
--code-highlight-kw-color: #ab8ac1;
|
||||
@ -2784,7 +2910,8 @@ Original by Dempfi (https://github.com/dempfi/ayu)
|
||||
--search-tab-button-not-selected-background: transparent !important;
|
||||
--search-tab-button-selected-border-top-color: none;
|
||||
--search-tab-button-selected-background: #141920 !important;
|
||||
--settings-menu-filter: invert(100%);
|
||||
--settings-menu-filter: invert(70%);
|
||||
--settings-menu-hover-filter: invert(100%);
|
||||
--stab-background-color: #314559;
|
||||
--stab-code-color: #e6e1cf;
|
||||
--code-highlight-kw-color: #ff7733;
|
||||
|
@ -1,6 +1,6 @@
|
||||
// Local js definitions:
|
||||
/* global addClass, getSettingValue, hasClass, searchState, updateLocalStorage */
|
||||
/* global onEach, onEachLazy, removeClass, getVar */
|
||||
/* global onEachLazy, removeClass, getVar */
|
||||
|
||||
"use strict";
|
||||
|
||||
@ -19,17 +19,25 @@ function resourcePath(basename, extension) {
|
||||
|
||||
function hideMain() {
|
||||
addClass(document.getElementById(MAIN_ID), "hidden");
|
||||
const toggle = document.getElementById("toggle-all-docs");
|
||||
if (toggle) {
|
||||
toggle.setAttribute("disabled", "disabled");
|
||||
}
|
||||
}
|
||||
|
||||
function showMain() {
|
||||
removeClass(document.getElementById(MAIN_ID), "hidden");
|
||||
}
|
||||
|
||||
function blurHandler(event, parentElem, hideCallback) {
|
||||
if (!parentElem.contains(document.activeElement) &&
|
||||
!parentElem.contains(event.relatedTarget)
|
||||
) {
|
||||
hideCallback();
|
||||
const main = document.getElementById(MAIN_ID);
|
||||
removeClass(main, "hidden");
|
||||
const mainHeading = main.querySelector(".main-heading");
|
||||
if (mainHeading && searchState.rustdocToolbar) {
|
||||
if (searchState.rustdocToolbar.parentElement) {
|
||||
searchState.rustdocToolbar.parentElement.removeChild(searchState.rustdocToolbar);
|
||||
}
|
||||
mainHeading.appendChild(searchState.rustdocToolbar);
|
||||
}
|
||||
const toggle = document.getElementById("toggle-all-docs");
|
||||
if (toggle) {
|
||||
toggle.removeAttribute("disabled");
|
||||
}
|
||||
}
|
||||
|
||||
@ -167,6 +175,14 @@ function switchDisplayedElement(elemToDisplay) {
|
||||
el.appendChild(elemToDisplay);
|
||||
hideMain();
|
||||
removeClass(el, "hidden");
|
||||
|
||||
const mainHeading = elemToDisplay.querySelector(".main-heading");
|
||||
if (mainHeading && searchState.rustdocToolbar) {
|
||||
if (searchState.rustdocToolbar.parentElement) {
|
||||
searchState.rustdocToolbar.parentElement.removeChild(searchState.rustdocToolbar);
|
||||
}
|
||||
mainHeading.appendChild(searchState.rustdocToolbar);
|
||||
}
|
||||
}
|
||||
|
||||
function browserSupportsHistoryApi() {
|
||||
@ -194,33 +210,36 @@ function preLoadCss(cssUrl) {
|
||||
document.head.append(script);
|
||||
}
|
||||
|
||||
getSettingsButton().onclick = event => {
|
||||
if (event.ctrlKey || event.altKey || event.metaKey) {
|
||||
return;
|
||||
}
|
||||
window.hideAllModals(false);
|
||||
addClass(getSettingsButton(), "rotate");
|
||||
event.preventDefault();
|
||||
// Sending request for the CSS and the JS files at the same time so it will
|
||||
// hopefully be loaded when the JS will generate the settings content.
|
||||
loadScript(getVar("static-root-path") + getVar("settings-js"));
|
||||
// Pre-load all theme CSS files, so that switching feels seamless.
|
||||
//
|
||||
// When loading settings.html as a standalone page, the equivalent HTML is
|
||||
// generated in context.rs.
|
||||
setTimeout(() => {
|
||||
const themes = getVar("themes").split(",");
|
||||
for (const theme of themes) {
|
||||
// if there are no themes, do nothing
|
||||
// "".split(",") == [""]
|
||||
if (theme !== "") {
|
||||
preLoadCss(getVar("root-path") + theme + ".css");
|
||||
}
|
||||
if (getSettingsButton()) {
|
||||
getSettingsButton().onclick = event => {
|
||||
if (event.ctrlKey || event.altKey || event.metaKey) {
|
||||
return;
|
||||
}
|
||||
}, 0);
|
||||
};
|
||||
window.hideAllModals(false);
|
||||
addClass(getSettingsButton(), "rotate");
|
||||
event.preventDefault();
|
||||
// Sending request for the CSS and the JS files at the same time so it will
|
||||
// hopefully be loaded when the JS will generate the settings content.
|
||||
loadScript(getVar("static-root-path") + getVar("settings-js"));
|
||||
// Pre-load all theme CSS files, so that switching feels seamless.
|
||||
//
|
||||
// When loading settings.html as a standalone page, the equivalent HTML is
|
||||
// generated in context.rs.
|
||||
setTimeout(() => {
|
||||
const themes = getVar("themes").split(",");
|
||||
for (const theme of themes) {
|
||||
// if there are no themes, do nothing
|
||||
// "".split(",") == [""]
|
||||
if (theme !== "") {
|
||||
preLoadCss(getVar("root-path") + theme + ".css");
|
||||
}
|
||||
}
|
||||
}, 0);
|
||||
};
|
||||
}
|
||||
|
||||
window.searchState = {
|
||||
rustdocToolbar: document.querySelector("rustdoc-toolbar"),
|
||||
loadingText: "Loading search results...",
|
||||
input: document.getElementsByClassName("search-input")[0],
|
||||
outputElement: () => {
|
||||
@ -919,8 +938,7 @@ function preLoadCss(cssUrl) {
|
||||
e.open = true;
|
||||
}
|
||||
});
|
||||
innerToggle.title = "collapse all docs";
|
||||
innerToggle.children[0].innerText = "\u2212"; // "\u2212" is "−" minus sign
|
||||
innerToggle.children[0].innerText = "Summary";
|
||||
}
|
||||
|
||||
function collapseAllDocs() {
|
||||
@ -934,8 +952,7 @@ function preLoadCss(cssUrl) {
|
||||
e.open = false;
|
||||
}
|
||||
});
|
||||
innerToggle.title = "expand all docs";
|
||||
innerToggle.children[0].innerText = "+";
|
||||
innerToggle.children[0].innerText = "Show all";
|
||||
}
|
||||
|
||||
function toggleAllDocs() {
|
||||
@ -1330,7 +1347,13 @@ function preLoadCss(cssUrl) {
|
||||
}
|
||||
|
||||
function helpBlurHandler(event) {
|
||||
blurHandler(event, getHelpButton(), window.hidePopoverMenus);
|
||||
if (!getHelpButton().contains(document.activeElement) &&
|
||||
!getHelpButton().contains(event.relatedTarget) &&
|
||||
!getSettingsButton().contains(document.activeElement) &&
|
||||
!getSettingsButton().contains(event.relatedTarget)
|
||||
) {
|
||||
window.hidePopoverMenus();
|
||||
}
|
||||
}
|
||||
|
||||
function buildHelpMenu() {
|
||||
@ -1433,9 +1456,13 @@ href="https://doc.rust-lang.org/${channel}/rustdoc/read-documentation/search.htm
|
||||
* Hide all the popover menus.
|
||||
*/
|
||||
window.hidePopoverMenus = () => {
|
||||
onEachLazy(document.querySelectorAll(".search-form .popover"), elem => {
|
||||
onEachLazy(document.querySelectorAll("rustdoc-toolbar .popover"), elem => {
|
||||
elem.style.display = "none";
|
||||
});
|
||||
const button = getHelpButton();
|
||||
if (button) {
|
||||
removeClass(button, "help-open");
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
@ -1460,7 +1487,9 @@ href="https://doc.rust-lang.org/${channel}/rustdoc/read-documentation/search.htm
|
||||
function showHelp() {
|
||||
// Prevent `blur` events from being dispatched as a result of closing
|
||||
// other modals.
|
||||
getHelpButton().querySelector("a").focus();
|
||||
const button = getHelpButton();
|
||||
addClass(button, "help-open");
|
||||
button.querySelector("a").focus();
|
||||
const menu = getHelpMenu(true);
|
||||
if (menu.style.display === "none") {
|
||||
window.hideAllModals();
|
||||
@ -1468,28 +1497,15 @@ href="https://doc.rust-lang.org/${channel}/rustdoc/read-documentation/search.htm
|
||||
}
|
||||
}
|
||||
|
||||
const helpLink = document.querySelector(`#${HELP_BUTTON_ID} > a`);
|
||||
if (isHelpPage) {
|
||||
showHelp();
|
||||
document.querySelector(`#${HELP_BUTTON_ID} > a`).addEventListener("click", event => {
|
||||
// Already on the help page, make help button a no-op.
|
||||
const target = event.target;
|
||||
if (target.tagName !== "A" ||
|
||||
target.parentElement.id !== HELP_BUTTON_ID ||
|
||||
event.ctrlKey ||
|
||||
event.altKey ||
|
||||
event.metaKey) {
|
||||
return;
|
||||
}
|
||||
event.preventDefault();
|
||||
});
|
||||
} else {
|
||||
document.querySelector(`#${HELP_BUTTON_ID} > a`).addEventListener("click", event => {
|
||||
buildHelpMenu();
|
||||
} else if (helpLink) {
|
||||
helpLink.addEventListener("click", event => {
|
||||
// By default, have help button open docs in a popover.
|
||||
// If user clicks with a moderator, though, use default browser behavior,
|
||||
// probably opening in a new window or tab.
|
||||
const target = event.target;
|
||||
if (target.tagName !== "A" ||
|
||||
target.parentElement.id !== HELP_BUTTON_ID ||
|
||||
if (!helpLink.contains(helpLink) ||
|
||||
event.ctrlKey ||
|
||||
event.altKey ||
|
||||
event.metaKey) {
|
||||
@ -1812,14 +1828,11 @@ href="https://doc.rust-lang.org/${channel}/rustdoc/read-documentation/search.htm
|
||||
return;
|
||||
}
|
||||
but.onclick = () => {
|
||||
const parent = but.parentElement;
|
||||
const path = [];
|
||||
|
||||
onEach(parent.childNodes, child => {
|
||||
if (child.tagName === "A") {
|
||||
path.push(child.textContent);
|
||||
}
|
||||
onEachLazy(document.querySelectorAll(".rustdoc-breadcrumbs a"), a => {
|
||||
path.push(a.textContent);
|
||||
});
|
||||
path.push(document.querySelector("title").textContent.split(" ")[0]);
|
||||
|
||||
copyContentToClipboard(path.join("::"));
|
||||
copyButtonAnimation(but);
|
||||
|
@ -3597,15 +3597,16 @@ async function showResults(results, go_to_first, filterCrates) {
|
||||
|
||||
let crates = "";
|
||||
if (rawSearchIndex.size > 1) {
|
||||
crates = " in <div id=\"crate-search-div\"><select id=\"crate-search\">" +
|
||||
"<option value=\"all crates\">all crates</option>";
|
||||
crates = "<div class=\"sub-heading\"> in <div id=\"crate-search-div\">" +
|
||||
"<select id=\"crate-search\"><option value=\"all crates\">all crates</option>";
|
||||
for (const c of rawSearchIndex.keys()) {
|
||||
crates += `<option value="${c}" ${c === filterCrates && "selected"}>${c}</option>`;
|
||||
}
|
||||
crates += "</select></div>";
|
||||
crates += "</select></div></div>";
|
||||
}
|
||||
|
||||
let output = `<h1 class="search-results-title">Results${crates}</h1>`;
|
||||
let output = `<div class="main-heading">\
|
||||
<h1 class="search-results-title">Results</h1>${crates}</div>`;
|
||||
if (results.query.error !== null) {
|
||||
const error = results.query.error;
|
||||
error.forEach((value, index) => {
|
||||
@ -3662,6 +3663,9 @@ async function showResults(results, go_to_first, filterCrates) {
|
||||
resultsElem.appendChild(ret_returned[0]);
|
||||
|
||||
search.innerHTML = output;
|
||||
if (searchState.rustdocToolbar) {
|
||||
search.querySelector(".main-heading").appendChild(searchState.rustdocToolbar);
|
||||
}
|
||||
const crateSearch = document.getElementById("crate-search");
|
||||
if (crateSearch) {
|
||||
crateSearch.addEventListener("input", updateCrate);
|
||||
|
@ -1,7 +1,7 @@
|
||||
// Local js definitions:
|
||||
/* global getSettingValue, updateLocalStorage, updateTheme */
|
||||
/* global addClass, removeClass, onEach, onEachLazy, blurHandler */
|
||||
/* global MAIN_ID, getVar, getSettingsButton */
|
||||
/* global addClass, removeClass, onEach, onEachLazy */
|
||||
/* global MAIN_ID, getVar, getSettingsButton, getHelpButton */
|
||||
|
||||
"use strict";
|
||||
|
||||
@ -267,15 +267,16 @@
|
||||
}
|
||||
|
||||
function settingsBlurHandler(event) {
|
||||
blurHandler(event, getSettingsButton(), window.hidePopoverMenus);
|
||||
if (!getHelpButton().contains(document.activeElement) &&
|
||||
!getHelpButton().contains(event.relatedTarget) &&
|
||||
!getSettingsButton().contains(document.activeElement) &&
|
||||
!getSettingsButton().contains(event.relatedTarget)
|
||||
) {
|
||||
window.hidePopoverMenus();
|
||||
}
|
||||
}
|
||||
|
||||
if (isSettingsPage) {
|
||||
// We replace the existing "onclick" callback to do nothing if clicked.
|
||||
getSettingsButton().onclick = event => {
|
||||
event.preventDefault();
|
||||
};
|
||||
} else {
|
||||
if (!isSettingsPage) {
|
||||
// We replace the existing "onclick" callback.
|
||||
const settingsButton = getSettingsButton();
|
||||
const settingsMenu = document.getElementById("settings");
|
||||
|
@ -274,16 +274,29 @@ class RustdocSearchElement extends HTMLElement {
|
||||
spellcheck="false"
|
||||
placeholder="Type ‘S’ or ‘/’ to search, ‘?’ for more options…"
|
||||
type="search">
|
||||
<div id="help-button" tabindex="-1">
|
||||
<a href="${rootPath}help.html" title="help">?</a>
|
||||
</div>
|
||||
<div id="settings-menu" tabindex="-1">
|
||||
<a href="${rootPath}settings.html" title="settings">
|
||||
Settings
|
||||
</a>
|
||||
</div>
|
||||
</form>
|
||||
</nav>`;
|
||||
}
|
||||
}
|
||||
window.customElements.define("rustdoc-search", RustdocSearchElement);
|
||||
class RustdocToolbarElement extends HTMLElement {
|
||||
constructor() {
|
||||
super();
|
||||
}
|
||||
connectedCallback() {
|
||||
// Avoid replacing the children after they're already here.
|
||||
if (this.firstElementChild) {
|
||||
return;
|
||||
}
|
||||
const rootPath = getVar("root-path");
|
||||
this.innerHTML = `
|
||||
<div id="settings-menu" tabindex="-1">
|
||||
<a href="${rootPath}settings.html"><span class="label">Settings</span></a>
|
||||
</div>
|
||||
<div id="help-button" tabindex="-1">
|
||||
<a href="${rootPath}help.html"><span class="label">Help</span></a>
|
||||
</div>
|
||||
<button id="toggle-all-docs"><span class="label">Summary</span></button>`;
|
||||
}
|
||||
}
|
||||
window.customElements.define("rustdoc-toolbar", RustdocToolbarElement);
|
||||
|
@ -1,26 +1,33 @@
|
||||
<div class="main-heading"> {# #}
|
||||
{% if !path_components.is_empty() %}
|
||||
<span class="rustdoc-breadcrumbs">
|
||||
{% for (i, component) in path_components.iter().enumerate() %}
|
||||
{% if i != 0 %}
|
||||
::<wbr>
|
||||
{% endif %}
|
||||
<a href="{{component.path|safe}}index.html">{{component.name}}</a>
|
||||
{% endfor %}
|
||||
</span>
|
||||
{% endif %}
|
||||
<h1>
|
||||
{{typ}}
|
||||
{# The breadcrumbs of the item path, like std::string #}
|
||||
{% for component in path_components %}
|
||||
<a href="{{component.path|safe}}index.html">{{component.name}}</a>::<wbr>
|
||||
{% endfor %}
|
||||
<a class="{{item_type}}" href="#">{{name}}</a> {# #}
|
||||
<span{% if item_type != "mod" +%} class="{{item_type}}"{% endif %}>
|
||||
{{name}}
|
||||
</span> {# #}
|
||||
<button id="copy-path" title="Copy item path to clipboard"> {# #}
|
||||
Copy item path {# #}
|
||||
</button> {# #}
|
||||
</h1> {# #}
|
||||
<span class="out-of-band">
|
||||
<rustdoc-toolbar></rustdoc-toolbar> {# #}
|
||||
<span class="sub-heading">
|
||||
{% if !stability_since_raw.is_empty() %}
|
||||
{{ stability_since_raw|safe +}} · {#+ #}
|
||||
{{ stability_since_raw|safe +}}
|
||||
{% endif %}
|
||||
{% match src_href %}
|
||||
{% when Some with (href) %}
|
||||
<a class="src" href="{{href|safe}}">source</a> · {#+ #}
|
||||
{% if !stability_since_raw.is_empty() +%} · {%+ endif %}
|
||||
<a class="src" href="{{href|safe}}">source</a> {#+ #}
|
||||
{% else %}
|
||||
{% endmatch %}
|
||||
<button id="toggle-all-docs" title="collapse all docs"> {# #}
|
||||
[<span>−</span>] {# #}
|
||||
</button> {# #}
|
||||
</span> {# #}
|
||||
</div> {# #}
|
||||
|
@ -1,4 +1,15 @@
|
||||
<div class="example-wrap">
|
||||
{% match file_path %}
|
||||
{% when Some with ((path, name)) %}
|
||||
<div class="main-heading"> {# #}
|
||||
<h1> {# #}
|
||||
<div class="sub-heading">{{path}}/</div>
|
||||
{{name}}
|
||||
</h1> {# #}
|
||||
<rustdoc-toolbar></rustdoc-toolbar> {# #}
|
||||
</div>
|
||||
{% else %}
|
||||
{% endmatch %}
|
||||
<div class="example-wrap"> {# #}
|
||||
{# https://developers.google.com/search/docs/crawling-indexing/robots-meta-tag#data-nosnippet-attr
|
||||
Do not show "1 2 3 4 5 ..." in web search results. #}
|
||||
<div data-nosnippet><pre class="src-line-numbers">
|
||||
|
@ -10,6 +10,7 @@
|
||||
#![feature(iter_intersperse)]
|
||||
#![feature(let_chains)]
|
||||
#![feature(never_type)]
|
||||
#![feature(os_str_display)]
|
||||
#![feature(round_char_boundary)]
|
||||
#![feature(test)]
|
||||
#![feature(type_alias_impl_trait)]
|
||||
|
@ -1963,7 +1963,7 @@ impl<'test> TestCx<'test> {
|
||||
|
||||
#[rustfmt::skip]
|
||||
let tidy_args = [
|
||||
"--new-blocklevel-tags", "rustdoc-search",
|
||||
"--new-blocklevel-tags", "rustdoc-search,rustdoc-toolbar",
|
||||
"--indent", "yes",
|
||||
"--indent-spaces", "2",
|
||||
"--wrap", "0",
|
||||
|
@ -31,7 +31,7 @@ fn check_html_file(file: &Path) -> usize {
|
||||
.arg("--mute-id") // this option is useful in case we want to mute more warnings
|
||||
.arg("yes")
|
||||
.arg("--new-blocklevel-tags")
|
||||
.arg("rustdoc-search") // custom elements
|
||||
.arg("rustdoc-search,rustdoc-toolbar") // custom elements
|
||||
.arg("--mute")
|
||||
.arg(&to_mute_s)
|
||||
.arg(file);
|
||||
|
@ -16,5 +16,5 @@ impl T1 for i32 {
|
||||
fn main() {
|
||||
let r = Box::new(0) as Box<dyn T1>;
|
||||
let r2: Box<dyn T2> = unsafe { std::mem::transmute(r) };
|
||||
r2.method2(); //~ERROR: using vtable for trait `T1` but trait `T2` was expected
|
||||
r2.method2(); //~ERROR: using vtable for `T1` but `T2` was expected
|
||||
}
|
||||
|
@ -1,8 +1,8 @@
|
||||
error: Undefined Behavior: using vtable for trait `T1` but trait `T2` was expected
|
||||
error: Undefined Behavior: using vtable for `T1` but `T2` was expected
|
||||
--> tests/fail/dyn-call-trait-mismatch.rs:LL:CC
|
||||
|
|
||||
LL | r2.method2();
|
||||
| ^^^^^^^^^^^^ using vtable for trait `T1` but trait `T2` was expected
|
||||
| ^^^^^^^^^^^^ using vtable for `T1` but `T2` was expected
|
||||
|
|
||||
= help: this indicates a bug in the program: it performed an invalid operation, and caused Undefined Behavior
|
||||
= help: see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information
|
||||
|
@ -63,6 +63,6 @@ fn main() {
|
||||
let baz: &dyn Baz = &1;
|
||||
let baz_fake: *const dyn Bar = std::mem::transmute(baz);
|
||||
let _err = baz_fake as *const dyn Foo;
|
||||
//~^ERROR: using vtable for trait `Baz` but trait `Bar` was expected
|
||||
//~^ERROR: using vtable for `Baz` but `Bar` was expected
|
||||
}
|
||||
}
|
||||
|
@ -1,8 +1,8 @@
|
||||
error: Undefined Behavior: using vtable for trait `Baz` but trait `Bar` was expected
|
||||
error: Undefined Behavior: using vtable for `Baz` but `Bar` was expected
|
||||
--> tests/fail/dyn-upcast-trait-mismatch.rs:LL:CC
|
||||
|
|
||||
LL | let _err = baz_fake as *const dyn Foo;
|
||||
| ^^^^^^^^ using vtable for trait `Baz` but trait `Bar` was expected
|
||||
| ^^^^^^^^ using vtable for `Baz` but `Bar` was expected
|
||||
|
|
||||
= help: this indicates a bug in the program: it performed an invalid operation, and caused Undefined Behavior
|
||||
= help: see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information
|
||||
|
@ -0,0 +1,18 @@
|
||||
trait Trait {
|
||||
type Assoc;
|
||||
fn foo(&self) -> Self::Assoc;
|
||||
}
|
||||
|
||||
impl<T: Copy> Trait for T {
|
||||
type Assoc = T;
|
||||
fn foo(&self) -> T { *self }
|
||||
}
|
||||
|
||||
fn main() {
|
||||
let v: Box<dyn Trait<Assoc = u8>> = Box::new(2);
|
||||
let v: Box<dyn Trait<Assoc = bool>> = unsafe { std::mem::transmute(v) }; //~ERROR: wrong trait
|
||||
|
||||
if v.foo() {
|
||||
println!("huh");
|
||||
}
|
||||
}
|
@ -0,0 +1,15 @@
|
||||
error: Undefined Behavior: constructing invalid value: wrong trait in wide pointer vtable: expected `Trait<Assoc = bool>`, but encountered `Trait<Assoc = u8>`
|
||||
--> tests/fail/validity/wrong-dyn-trait-assoc-type.rs:LL:CC
|
||||
|
|
||||
LL | let v: Box<dyn Trait<Assoc = bool>> = unsafe { std::mem::transmute(v) };
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value: wrong trait in wide pointer vtable: expected `Trait<Assoc = bool>`, but encountered `Trait<Assoc = u8>`
|
||||
|
|
||||
= help: this indicates a bug in the program: it performed an invalid operation, and caused Undefined Behavior
|
||||
= help: see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information
|
||||
= note: BACKTRACE:
|
||||
= note: inside `main` at tests/fail/validity/wrong-dyn-trait-assoc-type.rs:LL:CC
|
||||
|
||||
note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace
|
||||
|
||||
error: aborting due to 1 previous error
|
||||
|
@ -1,8 +1,8 @@
|
||||
error: Undefined Behavior: constructing invalid value: wrong trait in wide pointer vtable: expected `std::fmt::Debug`, but encountered `<trivial>`
|
||||
error: Undefined Behavior: constructing invalid value: wrong trait in wide pointer vtable: expected `std::fmt::Debug`, but encountered `std::marker::Send`
|
||||
--> tests/fail/validity/wrong-dyn-trait.rs:LL:CC
|
||||
|
|
||||
LL | let _y: *const dyn fmt::Debug = unsafe { mem::transmute(x) };
|
||||
| ^^^^^^^^^^^^^^^^^ constructing invalid value: wrong trait in wide pointer vtable: expected `std::fmt::Debug`, but encountered `<trivial>`
|
||||
| ^^^^^^^^^^^^^^^^^ constructing invalid value: wrong trait in wide pointer vtable: expected `std::fmt::Debug`, but encountered `std::marker::Send`
|
||||
|
|
||||
= help: this indicates a bug in the program: it performed an invalid operation, and caused Undefined Behavior
|
||||
= help: see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information
|
||||
|
@ -249,6 +249,9 @@
|
||||
//@ revisions: loongarch64_unknown_linux_musl
|
||||
//@ [loongarch64_unknown_linux_musl] compile-flags: --target loongarch64-unknown-linux-musl
|
||||
//@ [loongarch64_unknown_linux_musl] needs-llvm-components: loongarch
|
||||
//@ revisions: loongarch64_unknown_linux_ohos
|
||||
//@ [loongarch64_unknown_linux_ohos] compile-flags: --target loongarch64-unknown-linux-ohos
|
||||
//@ [loongarch64_unknown_linux_ohos] needs-llvm-components: loongarch
|
||||
//@ revisions: loongarch64_unknown_none
|
||||
//@ [loongarch64_unknown_none] compile-flags: --target loongarch64-unknown-none
|
||||
//@ [loongarch64_unknown_none] needs-llvm-components: loongarch
|
||||
|
15
tests/crashes/130310.rs
Normal file
15
tests/crashes/130310.rs
Normal file
@ -0,0 +1,15 @@
|
||||
//@ known-bug: rust-lang/rust#130310
|
||||
|
||||
use std::marker::PhantomData;
|
||||
|
||||
#[repr(C)]
|
||||
struct A<T> {
|
||||
a: *const A<A<T>>,
|
||||
p: PhantomData<T>,
|
||||
}
|
||||
|
||||
extern "C" {
|
||||
fn f(a: *const A<()>);
|
||||
}
|
||||
|
||||
fn main() {}
|
@ -12,8 +12,7 @@ define-function: (
|
||||
call-function: ("switch-theme", {"theme": |theme|})
|
||||
|
||||
assert-css: ("#toggle-all-docs", {"color": |main_color|})
|
||||
assert-css: (".main-heading h1 a:nth-of-type(1)", {"color": |main_heading_color|})
|
||||
assert-css: (".main-heading a:nth-of-type(2)", {"color": |main_heading_type_color|})
|
||||
assert-css: (".main-heading h1 span", {"color": |main_heading_type_color|})
|
||||
assert-css: (
|
||||
".rightside a.src",
|
||||
{"color": |src_link_color|, "text-decoration": "none solid " + |src_link_color|},
|
||||
@ -55,7 +54,7 @@ define-function: (
|
||||
assert-css: ("#top-doc-prose-title", {"color": |title_color|})
|
||||
|
||||
assert-css: (".sidebar .block a", {"color": |sidebar_link_color|})
|
||||
assert-css: (".main-heading h1 a", {"color": |title_color|})
|
||||
assert-css: (".main-heading h1", {"color": |title_color|})
|
||||
|
||||
// We move the cursor over the "Implementations" title so the anchor is displayed.
|
||||
move-cursor-to: "h2#implementations"
|
||||
|
@ -4,7 +4,7 @@ set-window-size: (1000, 1000) // Try desktop size first.
|
||||
wait-for: "#help"
|
||||
assert-css: ("#help", {"display": "block"})
|
||||
assert-css: ("#help dd", {"font-size": "16px"})
|
||||
click: "#help-button > a"
|
||||
assert-false: "#help-button > a"
|
||||
assert-css: ("#help", {"display": "block"})
|
||||
compare-elements-property: (".sub", "#help", ["offsetWidth"])
|
||||
compare-elements-position: (".sub", "#help", ["x"])
|
||||
@ -50,7 +50,8 @@ call-function: ("check-colors", {
|
||||
})
|
||||
|
||||
// This test ensures that opening the help popover without switching pages works.
|
||||
go-to: "file://" + |DOC_PATH| + "/test_docs/index.html"
|
||||
go-to: "file://" + |DOC_PATH| + "/test_docs/index.html?search=a"
|
||||
wait-for: "#search-tabs" // Waiting for the search.js to load.
|
||||
set-window-size: (1000, 1000) // Only supported on desktop.
|
||||
assert-false: "#help"
|
||||
click: "#help-button > a"
|
||||
@ -62,7 +63,8 @@ compare-elements-property-false: (".sub", "#help", ["offsetWidth"])
|
||||
compare-elements-position-false: (".sub", "#help", ["x"])
|
||||
|
||||
// This test ensures that the "the rustdoc book" anchor link within the help popover works.
|
||||
go-to: "file://" + |DOC_PATH| + "/test_docs/index.html"
|
||||
go-to: "file://" + |DOC_PATH| + "/test_docs/index.html?search=a"
|
||||
wait-for: "#search-tabs" // Waiting for the search.js to load.
|
||||
set-window-size: (1000, 1000) // Popover only appears when the screen width is >700px.
|
||||
assert-false: "#help"
|
||||
click: "#help-button > a"
|
||||
|
@ -20,7 +20,7 @@ store-position: (
|
||||
{"x": second_line_x, "y": second_line_y},
|
||||
)
|
||||
assert: |first_line_x| != |second_line_x| && |first_line_x| == 516 && |second_line_x| == 272
|
||||
assert: |first_line_y| != |second_line_y| && |first_line_y| == 688 && |second_line_y| == 711
|
||||
assert: |first_line_y| != |second_line_y| && |first_line_y| == 714 && |second_line_y| == 737
|
||||
|
||||
// Now we ensure that they're not rendered on the same line.
|
||||
set-window-size: (1100, 800)
|
||||
|
@ -5,23 +5,8 @@ set-window-size: (400, 600)
|
||||
set-font-size: 18
|
||||
wait-for: 100 // wait a bit for the resize and the font-size change to be fully taken into account.
|
||||
|
||||
// The out-of-band info (source, stable version, collapse) should be below the
|
||||
// h1 when the screen gets narrow enough.
|
||||
assert-css: (".main-heading", {
|
||||
"display": "flex",
|
||||
"flex-direction": "column"
|
||||
})
|
||||
|
||||
assert-property: (".mobile-topbar h2", {"offsetHeight": 33})
|
||||
|
||||
// Note: We can't use assert-text here because the 'Since' is set by CSS and
|
||||
// is therefore not part of the DOM.
|
||||
assert-css: (".content .out-of-band .since::before", { "content": "\"Since \"" })
|
||||
|
||||
set-window-size: (1000, 1000)
|
||||
wait-for: 100 // wait a bit for the resize to be fully taken into account.
|
||||
assert-css-false: (".content .out-of-band .since::before", { "content": "\"Since \"" })
|
||||
|
||||
// On the settings page, the theme buttons should not line-wrap. Instead, they should
|
||||
// all be placed as a group on a line below the setting name "Theme."
|
||||
go-to: "file://" + |DOC_PATH| + "/settings.html"
|
||||
|
@ -248,12 +248,13 @@ click: "//*[@id='method.create_an_iterator_from_read']//*[@class='tooltip']"
|
||||
assert-count: ("//*[@class='tooltip popover']", 1)
|
||||
assert-false: "//*[@class='sidebar shown']"
|
||||
|
||||
// Also check the focus handling for the help button.
|
||||
// Also check the focus handling for the settings button.
|
||||
set-window-size: (1100, 600)
|
||||
reload:
|
||||
assert-count: ("//*[@class='tooltip popover']", 0)
|
||||
click: "//*[@id='method.create_an_iterator_from_read']//*[@class='tooltip']"
|
||||
assert-count: ("//*[@class='tooltip popover']", 1)
|
||||
click: "#help-button a"
|
||||
click: "#settings-menu a"
|
||||
wait-for: "#settings"
|
||||
assert-count: ("//*[@class='tooltip popover']", 0)
|
||||
assert-false: "#method\.create_an_iterator_from_read .tooltip:focus"
|
||||
|
@ -1,6 +1,7 @@
|
||||
// This test ensures that the "pocket menus" are working as expected.
|
||||
include: "utils.goml"
|
||||
go-to: "file://" + |DOC_PATH| + "/test_docs/index.html"
|
||||
go-to: "file://" + |DOC_PATH| + "/test_docs/index.html?search=test"
|
||||
wait-for: "#crate-search"
|
||||
// First we check that the help menu doesn't exist yet.
|
||||
assert-false: "#help-button .popover"
|
||||
// Then we display the help menu.
|
||||
|
@ -80,8 +80,8 @@ click: ".scraped-example .button-holder .expand"
|
||||
store-value: (offset_y, 4)
|
||||
|
||||
// First with desktop
|
||||
assert-position: (".scraped-example", {"y": 226})
|
||||
assert-position: (".scraped-example .prev", {"y": 226 + |offset_y|})
|
||||
assert-position: (".scraped-example", {"y": 252})
|
||||
assert-position: (".scraped-example .prev", {"y": 252 + |offset_y|})
|
||||
|
||||
// Gradient background should be at the top of the code block.
|
||||
assert-css: (".scraped-example .example-wrap::before", {"top": "0px"})
|
||||
@ -90,8 +90,8 @@ assert-css: (".scraped-example .example-wrap::after", {"bottom": "0px"})
|
||||
// Then with mobile
|
||||
set-window-size: (600, 600)
|
||||
store-size: (".scraped-example .scraped-example-title", {"height": title_height})
|
||||
assert-position: (".scraped-example", {"y": 284})
|
||||
assert-position: (".scraped-example .prev", {"y": 284 + |offset_y| + |title_height|})
|
||||
assert-position: (".scraped-example", {"y": 281})
|
||||
assert-position: (".scraped-example .prev", {"y": 281 + |offset_y| + |title_height|})
|
||||
|
||||
define-function: (
|
||||
"check_title_and_code_position",
|
||||
|
@ -56,7 +56,8 @@ assert-property: ("#crate-search", {"value": "lib2"})
|
||||
assert-false: "#results .externcrate"
|
||||
|
||||
// Checking that the text for the "title" is correct (the "all crates" comes from the "<select>").
|
||||
assert-text: (".search-results-title", "Results in all crates", STARTS_WITH)
|
||||
assert-text: (".search-results-title", "Results", STARTS_WITH)
|
||||
assert-text: (".search-results-title + .sub-heading", " in all crates", STARTS_WITH)
|
||||
|
||||
// Checking the display of the crate filter.
|
||||
// We start with the light theme.
|
||||
@ -84,6 +85,6 @@ wait-for-css: ("#crate-search", {
|
||||
click: "#theme-ayu"
|
||||
wait-for-css: ("#crate-search", {
|
||||
"border": "1px solid #5c6773",
|
||||
"color": "#fff",
|
||||
"color": "#c5c5c5",
|
||||
"background-color": "#0f1419",
|
||||
})
|
||||
|
@ -1,13 +1,14 @@
|
||||
// This test ensures that the elements in ".search-form" have the expected display.
|
||||
include: "utils.goml"
|
||||
go-to: "file://" + |DOC_PATH| + "/test_docs/index.html"
|
||||
go-to: "file://" + |DOC_PATH| + "/test_docs/index.html?search=test"
|
||||
wait-for: "#search-tabs" // Waiting for the search.js to load.
|
||||
show-text: true
|
||||
|
||||
define-function: (
|
||||
"check-search-colors",
|
||||
[
|
||||
theme, border, background, search_input_color, search_input_border_focus,
|
||||
menu_button_border, menu_button_a_color, menu_button_a_border_hover, menu_a_color,
|
||||
menu_button_a_color, menu_button_a_border_hover, menu_a_color,
|
||||
],
|
||||
block {
|
||||
call-function: ("switch-theme", {"theme": |theme|})
|
||||
@ -29,30 +30,22 @@ define-function: (
|
||||
"color": |search_input_color|,
|
||||
},
|
||||
)
|
||||
assert-css: (
|
||||
"#help-button",
|
||||
{"border-color": |menu_button_border|},
|
||||
)
|
||||
assert-css: (
|
||||
"#help-button > a",
|
||||
{
|
||||
"color": |menu_button_a_color|,
|
||||
"border-color": |border|,
|
||||
"background-color": |background|,
|
||||
"border-color": "transparent",
|
||||
"background-color": "transparent",
|
||||
},
|
||||
)
|
||||
// Hover help button.
|
||||
move-cursor-to: "#help-button"
|
||||
assert-css: (
|
||||
"#help-button:hover",
|
||||
{"border-color": |menu_button_border|},
|
||||
)
|
||||
assert-css: (
|
||||
"#help-button > a",
|
||||
{
|
||||
"color": |menu_button_a_color|,
|
||||
"border-color": |menu_button_a_border_hover|,
|
||||
"background-color": |background|,
|
||||
"background-color": "transparent",
|
||||
},
|
||||
)
|
||||
// Link color inside
|
||||
@ -63,30 +56,22 @@ define-function: (
|
||||
"color": |menu_a_color|,
|
||||
},
|
||||
)
|
||||
assert-css: (
|
||||
"#settings-menu",
|
||||
{"border-color": |menu_button_border|},
|
||||
)
|
||||
assert-css: (
|
||||
"#settings-menu > a",
|
||||
{
|
||||
"color": |menu_button_a_color|,
|
||||
"border-color": |border|,
|
||||
"background-color": |background|,
|
||||
"border-color": "transparent",
|
||||
"background-color": "transparent",
|
||||
},
|
||||
)
|
||||
// Hover settings menu.
|
||||
move-cursor-to: "#settings-menu"
|
||||
assert-css: (
|
||||
"#settings-menu:hover",
|
||||
{"border-color": |menu_button_border|},
|
||||
)
|
||||
assert-css: (
|
||||
"#settings-menu:hover > a",
|
||||
{
|
||||
"color": |menu_button_a_color|,
|
||||
"border-color": |menu_button_a_border_hover|,
|
||||
"background-color": |background|,
|
||||
"background-color": "transparent",
|
||||
},
|
||||
)
|
||||
},
|
||||
@ -100,8 +85,7 @@ call-function: (
|
||||
"background": "#141920",
|
||||
"search_input_color": "#fff",
|
||||
"search_input_border_focus": "#5c6773",
|
||||
"menu_button_border": "#c5c5c5",
|
||||
"menu_button_a_color": "#fff",
|
||||
"menu_button_a_color": "#c5c5c5",
|
||||
"menu_button_a_border_hover": "#e0e0e0",
|
||||
"menu_a_color": "#39afd7",
|
||||
}
|
||||
@ -114,8 +98,7 @@ call-function: (
|
||||
"background": "#f0f0f0",
|
||||
"search_input_color": "#111",
|
||||
"search_input_border_focus": "#008dfd",
|
||||
"menu_button_border": "#ddd",
|
||||
"menu_button_a_color": "#000",
|
||||
"menu_button_a_color": "#ddd",
|
||||
"menu_button_a_border_hover": "#ffb900",
|
||||
"menu_a_color": "#d2991d",
|
||||
}
|
||||
@ -128,7 +111,6 @@ call-function: (
|
||||
"background": "#fff",
|
||||
"search_input_color": "#000",
|
||||
"search_input_border_focus": "#66afe9",
|
||||
"menu_button_border": "#000",
|
||||
"menu_button_a_color": "#000",
|
||||
"menu_button_a_border_hover": "#717171",
|
||||
"menu_a_color": "#3873ad",
|
||||
|
@ -50,8 +50,11 @@ compare-elements-size-near: (
|
||||
set-window-size: (900, 900)
|
||||
|
||||
// First we check the current width, height and position.
|
||||
assert-css: ("#crate-search", {"width": "223px"})
|
||||
assert-css: (".search-results-title", {"height": "50px", "width": "640px"})
|
||||
assert-css: ("#crate-search", {"width": "159px"})
|
||||
store-size: (".search-results-title", {
|
||||
"height": search_results_title_height,
|
||||
"width": search_results_title_width,
|
||||
})
|
||||
assert-css: ("#search", {"width": "640px"})
|
||||
|
||||
// Then we update the text of one of the `<option>`.
|
||||
@ -61,10 +64,12 @@ set-text: (
|
||||
)
|
||||
|
||||
// Then we compare again to confirm the height didn't change.
|
||||
assert-size: ("#crate-search", {"width": 527})
|
||||
assert-size: (".search-results-title", {"height": 50, "width": 640})
|
||||
// And we check that the `<select>` isn't bigger than its container (".search-results-title").
|
||||
assert-size: ("#crate-search", {"width": 509})
|
||||
assert-size: (".search-results-title", {
|
||||
"height": |search_results_title_height|,
|
||||
})
|
||||
assert-css: ("#search", {"width": "640px"})
|
||||
assert: |search_results_title_width| <= 640
|
||||
|
||||
// Now checking that the crate filter is working as expected too.
|
||||
show-text: true
|
||||
|
@ -16,4 +16,5 @@ assert-css: ("#main-content", {"display": "none"})
|
||||
// Now we can check that the feature is working as expected!
|
||||
go-to: "file://" + |DOC_PATH| + "/test_docs/index.html?search=struct%3AFoo&go_to_first=true"
|
||||
// Waiting for the page to load...
|
||||
wait-for-text: (".main-heading h1", "Struct test_docs::FooCopy item path")
|
||||
wait-for-text: (".main-heading .rustdoc-breadcrumbs", "test_docs")
|
||||
wait-for-text: (".main-heading h1", "Struct FooCopy item path")
|
||||
|
@ -11,8 +11,8 @@ define-function: (
|
||||
call-function: ("switch-theme", {"theme": |theme|})
|
||||
assert-css: ("#settings-menu > a::before", {
|
||||
"filter": |filter|,
|
||||
"width": "22px",
|
||||
"height": "22px",
|
||||
"width": "18px",
|
||||
"height": "18px",
|
||||
})
|
||||
}
|
||||
)
|
||||
@ -23,9 +23,9 @@ call-function: ("check-image", {
|
||||
})
|
||||
call-function: ("check-image", {
|
||||
"theme": "dark",
|
||||
"filter": "none",
|
||||
"filter": "invert(0.65)",
|
||||
})
|
||||
call-function: ("check-image", {
|
||||
"theme": "light",
|
||||
"filter": "none",
|
||||
"filter": "invert(0.35)",
|
||||
})
|
||||
|
@ -305,6 +305,7 @@ wait-for-css: ("#help-button .popover", {"display": "block"})
|
||||
// Now we go to the settings page to check that the CSS is loaded as expected.
|
||||
go-to: "file://" + |DOC_PATH| + "/settings.html"
|
||||
wait-for: "#settings"
|
||||
assert-false: "#settings-menu"
|
||||
assert-css: (".setting-radio", {"cursor": "pointer"})
|
||||
|
||||
assert-attribute-false: ("#settings", {"class": "popover"}, CONTAINS)
|
||||
@ -324,6 +325,5 @@ javascript: true
|
||||
show-text: true
|
||||
reload:
|
||||
set-window-size: (300, 1000)
|
||||
click: "#settings-menu"
|
||||
wait-for: "#settings"
|
||||
assert-css: (".setting-radio", {"cursor": "pointer"})
|
||||
|
@ -13,19 +13,19 @@ press-key: "Escape"
|
||||
assert-css: ("#help-button .popover", {"display": "none"})
|
||||
// Checking doc collapse and expand.
|
||||
// It should be displaying a "-":
|
||||
assert-text: ("#toggle-all-docs", "[−]")
|
||||
assert-text: ("#toggle-all-docs", "Summary")
|
||||
press-key: "-"
|
||||
wait-for-text: ("#toggle-all-docs", "[+]")
|
||||
wait-for-text: ("#toggle-all-docs", "Show all")
|
||||
assert-attribute: ("#toggle-all-docs", {"class": "will-expand"})
|
||||
// Pressing it again shouldn't do anything.
|
||||
press-key: "-"
|
||||
assert-text: ("#toggle-all-docs", "[+]")
|
||||
assert-text: ("#toggle-all-docs", "Show all")
|
||||
assert-attribute: ("#toggle-all-docs", {"class": "will-expand"})
|
||||
// Expanding now.
|
||||
press-key: "+"
|
||||
wait-for-text: ("#toggle-all-docs", "[−]")
|
||||
wait-for-text: ("#toggle-all-docs", "Summary")
|
||||
assert-attribute: ("#toggle-all-docs", {"class": ""})
|
||||
// Pressing it again shouldn't do anything.
|
||||
press-key: "+"
|
||||
assert-text: ("#toggle-all-docs", "[−]")
|
||||
assert-text: ("#toggle-all-docs", "Summary")
|
||||
assert-attribute: ("#toggle-all-docs", {"class": ""})
|
||||
|
@ -141,7 +141,7 @@ click: "#sidebar-button"
|
||||
wait-for-css: (".src .sidebar > *", {"visibility": "hidden"})
|
||||
// We scroll to line 117 to change the scroll position.
|
||||
scroll-to: '//*[@id="117"]'
|
||||
store-value: (y_offset, "2493")
|
||||
store-value: (y_offset, "2564")
|
||||
assert-window-property: {"pageYOffset": |y_offset|}
|
||||
// Expanding the sidebar...
|
||||
click: "#sidebar-button"
|
||||
|
@ -160,12 +160,12 @@ click: "//ul[@class='block mod']/preceding-sibling::h3/a"
|
||||
// PAGE: index.html
|
||||
assert-css: ("#modules", {"background-color": "#fdffd3"})
|
||||
|
||||
// Finally, assert that the `[+]/[−]` toggle doesn't affect sidebar width.
|
||||
// Finally, assert that the Summary toggle doesn't affect sidebar width.
|
||||
click: "#toggle-all-docs"
|
||||
assert-text: ("#toggle-all-docs", "[+]")
|
||||
assert-text: ("#toggle-all-docs", "Show all")
|
||||
assert-property: (".sidebar", {"clientWidth": "200"})
|
||||
click: "#toggle-all-docs"
|
||||
assert-text: ("#toggle-all-docs", "[−]")
|
||||
assert-text: ("#toggle-all-docs", "Summary")
|
||||
assert-property: (".sidebar", {"clientWidth": "200"})
|
||||
|
||||
// Checks that all.html and index.html have their sidebar link in the same place.
|
||||
|
@ -8,13 +8,13 @@ set-window-size: (600, 800)
|
||||
assert-property: ("html", {"scrollTop": "0"})
|
||||
|
||||
click: '//a[text() = "barbar" and @href="#5-7"]'
|
||||
assert-property: ("html", {"scrollTop": "123"})
|
||||
assert-property: ("html", {"scrollTop": "194"})
|
||||
click: '//a[text() = "bar" and @href="#28-36"]'
|
||||
assert-property: ("html", {"scrollTop": "154"})
|
||||
assert-property: ("html", {"scrollTop": "225"})
|
||||
click: '//a[normalize-space() = "sub_fn" and @href="#2-4"]'
|
||||
assert-property: ("html", {"scrollTop": "51"})
|
||||
assert-property: ("html", {"scrollTop": "122"})
|
||||
|
||||
// We now check that clicking on lines doesn't change the scroll
|
||||
// Extra information: the "sub_fn" function header is on line 1.
|
||||
click: '//*[@id="6"]'
|
||||
assert-property: ("html", {"scrollTop": "51"})
|
||||
assert-property: ("html", {"scrollTop": "122"})
|
||||
|
@ -89,9 +89,9 @@ assert-css: (".src-line-numbers", {"text-align": "right"})
|
||||
// do anything (and certainly not add a `#NaN` to the URL!).
|
||||
go-to: "file://" + |DOC_PATH| + "/src/test_docs/lib.rs.html"
|
||||
// We use this assert-position to know where we will click.
|
||||
assert-position: ("//*[@id='1']", {"x": 88, "y": 86})
|
||||
assert-position: ("//*[@id='1']", {"x": 88, "y": 163})
|
||||
// We click on the left of the "1" anchor but still in the "src-line-number" `<pre>`.
|
||||
click: (87, 77)
|
||||
click: (163, 77)
|
||||
assert-document-property: ({"URL": "/lib.rs.html"}, ENDS_WITH)
|
||||
|
||||
// Checking the source code sidebar.
|
||||
@ -159,19 +159,21 @@ call-function: ("check-sidebar-dir-entry", {
|
||||
// Check the search form
|
||||
assert-css: ("nav.sub", {"flex-direction": "row"})
|
||||
// The goal of this test is to ensure the search input is perfectly centered
|
||||
// between the top of the page and the top of the gray code block.
|
||||
// between the top of the page and the header.
|
||||
// To check this, we maintain the invariant:
|
||||
//
|
||||
// offsetTop[nav.sub form] = offsetTop[#main-content] - offsetHeight[nav.sub form] - offsetTop[nav.sub form]
|
||||
assert-property: ("nav.sub form", {"offsetTop": 15, "offsetHeight": 34})
|
||||
assert-property: ("#main-content", {"offsetTop": 64})
|
||||
assert-position: ("nav.sub form", {"y": 15})
|
||||
assert-property: ("nav.sub form", {"offsetHeight": 34})
|
||||
assert-position: ("h1", {"y": 64})
|
||||
// 15 = 64 - 34 - 15
|
||||
|
||||
// Now do the same check on moderately-sized, tablet mobile.
|
||||
set-window-size: (700, 700)
|
||||
assert-css: ("nav.sub", {"flex-direction": "row"})
|
||||
assert-property: ("nav.sub form", {"offsetTop": 8, "offsetHeight": 34})
|
||||
assert-property: ("#main-content", {"offsetTop": 50})
|
||||
assert-position: ("nav.sub form", {"y": 8})
|
||||
assert-property: ("nav.sub form", {"offsetHeight": 34})
|
||||
assert-position: ("h1", {"y": 50})
|
||||
// 8 = 50 - 34 - 8
|
||||
|
||||
// Check the sidebar directory entries have a marker and spacing (tablet).
|
||||
|
@ -52,6 +52,8 @@
|
||||
--search-tab-button-selected-border-top-color: #0089ff;
|
||||
--search-tab-button-selected-background: #fff;
|
||||
--settings-menu-filter: none;
|
||||
--settings-menu-hover-filter: invert(35%);
|
||||
--settings-menu-disabled-filter: invert(14%) sepia(11%) saturate(14%) hue-rotate(337deg);
|
||||
--stab-background-color: #fff5d6;
|
||||
--stab-code-color: #000;
|
||||
--code-highlight-kw-color: #8959a8;
|
||||
|
@ -12,4 +12,5 @@ assert-attribute-false: (".impl-items .toggle", {"open": ""})
|
||||
|
||||
// Click the "Trait" part of "impl Trait" and verify it navigates.
|
||||
click: "#impl-Trait-for-Foo h3 a:first-of-type"
|
||||
assert-text: (".main-heading h1", "Trait lib2::TraitCopy item path")
|
||||
assert-text: (".main-heading .rustdoc-breadcrumbs", "lib2")
|
||||
assert-text: (".main-heading h1", "Trait TraitCopy item path")
|
||||
|
@ -3,12 +3,12 @@
|
||||
go-to: "file://" + |DOC_PATH| + "/test_docs/struct.Foo.html"
|
||||
set-window-size: (433, 600)
|
||||
assert-attribute: (".top-doc", {"open": ""})
|
||||
click: (4, 270) // This is the position of the top doc comment toggle
|
||||
click: (4, 260) // This is the position of the top doc comment toggle
|
||||
assert-attribute-false: (".top-doc", {"open": ""})
|
||||
click: (4, 270)
|
||||
click: (4, 260)
|
||||
assert-attribute: (".top-doc", {"open": ""})
|
||||
// To ensure that the toggle isn't over the text, we check that the toggle isn't clicked.
|
||||
click: (3, 270)
|
||||
click: (3, 260)
|
||||
assert-attribute: (".top-doc", {"open": ""})
|
||||
|
||||
// Assert the position of the toggle on the top doc block.
|
||||
@ -24,10 +24,10 @@ assert-position: (
|
||||
// Now we do the same but with a little bigger width
|
||||
set-window-size: (600, 600)
|
||||
assert-attribute: (".top-doc", {"open": ""})
|
||||
click: (4, 270) // New Y position since all search elements are back on one line.
|
||||
click: (4, 260) // New Y position since all search elements are back on one line.
|
||||
assert-attribute-false: (".top-doc", {"open": ""})
|
||||
click: (4, 270)
|
||||
click: (4, 260)
|
||||
assert-attribute: (".top-doc", {"open": ""})
|
||||
// To ensure that the toggle isn't over the text, we check that the toggle isn't clicked.
|
||||
click: (3, 270)
|
||||
click: (3, 260)
|
||||
assert-attribute: (".top-doc", {"open": ""})
|
||||
|
@ -2,12 +2,12 @@
|
||||
include: "utils.goml"
|
||||
go-to: "file://" + |DOC_PATH| + "/test_docs/index.html"
|
||||
assert-attribute: ("#main-content > details.top-doc", {"open": ""})
|
||||
assert-text: ("#toggle-all-docs", "[−]")
|
||||
assert-text: ("#toggle-all-docs", "Summary")
|
||||
click: "#toggle-all-docs"
|
||||
wait-for: 50
|
||||
// This is now collapsed so there shouldn't be the "open" attribute on details.
|
||||
assert-attribute-false: ("#main-content > details.top-doc", {"open": ""})
|
||||
assert-text: ("#toggle-all-docs", "[+]")
|
||||
assert-text: ("#toggle-all-docs", "Show all")
|
||||
assert-css: (
|
||||
"#main-content > details.top-doc > summary",
|
||||
{"font-family": '"Fira Sans", Arial, NanumBarunGothic, sans-serif'},
|
||||
@ -15,12 +15,12 @@ assert-css: (
|
||||
click: "#toggle-all-docs"
|
||||
// Not collapsed anymore so the "open" attribute should be back.
|
||||
wait-for-attribute: ("#main-content > details.top-doc", {"open": ""})
|
||||
assert-text: ("#toggle-all-docs", "[−]")
|
||||
assert-text: ("#toggle-all-docs", "Summary")
|
||||
|
||||
// Check that it works on non-module pages as well.
|
||||
go-to: "file://" + |DOC_PATH| + "/test_docs/struct.Foo.html"
|
||||
// We first check that everything is visible.
|
||||
assert-text: ("#toggle-all-docs", "[−]")
|
||||
assert-text: ("#toggle-all-docs", "Summary")
|
||||
assert-attribute: ("#implementations-list details.toggle", {"open": ""}, ALL)
|
||||
assert-attribute: ("#trait-implementations-list details.toggle", {"open": ""}, ALL)
|
||||
assert-attribute-false: (
|
||||
@ -31,7 +31,7 @@ assert-attribute-false: (
|
||||
|
||||
// We collapse them all.
|
||||
click: "#toggle-all-docs"
|
||||
wait-for-text: ("#toggle-all-docs", "[+]")
|
||||
wait-for-text: ("#toggle-all-docs", "Show all")
|
||||
// We check that all <details> are collapsed (except for the impl block ones).
|
||||
assert-attribute-false: ("details.toggle:not(.implementors-toggle)", {"open": ""}, ALL)
|
||||
assert-attribute: ("#implementations-list > details.implementors-toggle", {"open": ""})
|
||||
@ -43,7 +43,7 @@ assert-attribute-false: (
|
||||
)
|
||||
// We open them all again.
|
||||
click: "#toggle-all-docs"
|
||||
wait-for-text: ("#toggle-all-docs", "[−]")
|
||||
wait-for-text: ("#toggle-all-docs", "Summary")
|
||||
assert-attribute: ("details.toggle", {"open": ""}, ALL)
|
||||
|
||||
// Checking the toggles style.
|
||||
|
@ -51,22 +51,23 @@ store-property: (".mobile-topbar", {"scrollWidth": scrollWidth})
|
||||
assert-property: (".mobile-topbar", {"clientWidth": |scrollWidth|})
|
||||
assert-css: (".mobile-topbar h2", {"overflow-x": "hidden"})
|
||||
|
||||
// Check wrapping for top main-heading h1 and out-of-band.
|
||||
// On desktop, they wrap when too big.
|
||||
// Check that main heading and toolbar go side-by-side, both on desktop and on mobile.
|
||||
set-window-size: (1100, 800)
|
||||
go-to: "file://" + |DOC_PATH| + "/lib2/too_long/struct.SuperIncrediblyLongLongLongLongLongLongLongGigaGigaGigaMegaLongLongLongStructName.html"
|
||||
compare-elements-position-false: (".main-heading h1", ".main-heading .out-of-band", ["y"])
|
||||
compare-elements-position: (".main-heading h1", ".main-heading rustdoc-toolbar", ["y"])
|
||||
compare-elements-position-near-false: (".main-heading h1", ".main-heading rustdoc-toolbar", {"x": 550})
|
||||
go-to: "file://" + |DOC_PATH| + "/lib2/index.html"
|
||||
compare-elements-position: (".main-heading h1", ".main-heading .out-of-band", ["y"])
|
||||
// make sure there is a gap between them
|
||||
compare-elements-position-near-false: (".main-heading h1", ".main-heading .out-of-band", {"x": 550})
|
||||
compare-elements-position: (".main-heading h1", ".main-heading rustdoc-toolbar", ["y"])
|
||||
compare-elements-position-near-false: (".main-heading h1", ".main-heading rustdoc-toolbar", {"x": 550})
|
||||
|
||||
// On mobile, they always wrap.
|
||||
set-window-size: (600, 600)
|
||||
go-to: "file://" + |DOC_PATH| + "/lib2/too_long/struct.SuperIncrediblyLongLongLongLongLongLongLongGigaGigaGigaMegaLongLongLongStructName.html"
|
||||
compare-elements-position-false: (".main-heading h1", ".main-heading .out-of-band", ["y"])
|
||||
compare-elements-position: (".main-heading h1", ".main-heading rustdoc-toolbar", ["y"])
|
||||
compare-elements-position-near-false: (".main-heading h1", ".main-heading rustdoc-toolbar", {"x": 200})
|
||||
go-to: "file://" + |DOC_PATH| + "/lib2/index.html"
|
||||
compare-elements-position-false: (".main-heading h1", ".main-heading .out-of-band", ["y"])
|
||||
compare-elements-position: (".main-heading h1", ".main-heading rustdoc-toolbar", ["y"])
|
||||
compare-elements-position-near-false: (".main-heading h1", ".main-heading rustdoc-toolbar", {"x": 200})
|
||||
|
||||
// Now we will check that the scrolling is working.
|
||||
// First on an item with "hidden methods".
|
||||
|
@ -2,15 +2,18 @@
|
||||
|
||||
//@ has 'empty_mod_private/index.html' '//a[@href="foo/index.html"]' 'foo'
|
||||
//@ hasraw 'empty_mod_private/sidebar-items.js' 'foo'
|
||||
//@ matches 'empty_mod_private/foo/index.html' '//h1' 'Module empty_mod_private::foo'
|
||||
//@ matches 'empty_mod_private/foo/index.html' '//h1' 'Module foo'
|
||||
//@ matches - '//*[@class="rustdoc-breadcrumbs"]' 'empty_mod_private'
|
||||
mod foo {}
|
||||
|
||||
//@ has 'empty_mod_private/index.html' '//a[@href="bar/index.html"]' 'bar'
|
||||
//@ hasraw 'empty_mod_private/sidebar-items.js' 'bar'
|
||||
//@ matches 'empty_mod_private/bar/index.html' '//h1' 'Module empty_mod_private::bar'
|
||||
//@ matches 'empty_mod_private/bar/index.html' '//h1' 'Module bar'
|
||||
//@ matches - '//*[@class="rustdoc-breadcrumbs"]' 'empty_mod_private'
|
||||
mod bar {
|
||||
//@ has 'empty_mod_private/bar/index.html' '//a[@href="baz/index.html"]' 'baz'
|
||||
//@ hasraw 'empty_mod_private/bar/sidebar-items.js' 'baz'
|
||||
//@ matches 'empty_mod_private/bar/baz/index.html' '//h1' 'Module empty_mod_private::bar::baz'
|
||||
//@ matches 'empty_mod_private/bar/baz/index.html' '//h1' 'Module baz'
|
||||
//@ matches - '//*[@class="rustdoc-breadcrumbs"]' 'empty_mod_private::bar'
|
||||
mod baz {}
|
||||
}
|
||||
|
@ -1,14 +1,17 @@
|
||||
//@ has 'empty_mod_public/index.html' '//a[@href="foo/index.html"]' 'foo'
|
||||
//@ hasraw 'empty_mod_public/sidebar-items.js' 'foo'
|
||||
//@ matches 'empty_mod_public/foo/index.html' '//h1' 'Module empty_mod_public::foo'
|
||||
//@ matches 'empty_mod_public/foo/index.html' '//h1' 'Module foo'
|
||||
//@ matches - '//*[@class="rustdoc-breadcrumbs"]' 'empty_mod_public'
|
||||
pub mod foo {}
|
||||
|
||||
//@ has 'empty_mod_public/index.html' '//a[@href="bar/index.html"]' 'bar'
|
||||
//@ hasraw 'empty_mod_public/sidebar-items.js' 'bar'
|
||||
//@ matches 'empty_mod_public/bar/index.html' '//h1' 'Module empty_mod_public::bar'
|
||||
//@ matches 'empty_mod_public/bar/index.html' '//h1' 'Module bar'
|
||||
//@ matches - '//*[@class="rustdoc-breadcrumbs"]' 'empty_mod_public'
|
||||
pub mod bar {
|
||||
//@ has 'empty_mod_public/bar/index.html' '//a[@href="baz/index.html"]' 'baz'
|
||||
//@ hasraw 'empty_mod_public/bar/sidebar-items.js' 'baz'
|
||||
//@ matches 'empty_mod_public/bar/baz/index.html' '//h1' 'Module empty_mod_public::bar::baz'
|
||||
//@ matches 'empty_mod_public/bar/baz/index.html' '//h1' 'Module baz'
|
||||
//@ matches - '//*[@class="rustdoc-breadcrumbs"]' 'empty_mod_public::bar'
|
||||
pub mod baz {}
|
||||
}
|
||||
|
@ -11,14 +11,14 @@
|
||||
//@ files 'src/foo' '[]'
|
||||
|
||||
//@ has foo/fn.foo.html
|
||||
//@ has - '//div[@class="main-heading"]/*[@class="out-of-band"]' '1.0.0 · '
|
||||
//@ !has - '//div[@class="main-heading"]/*[@class="out-of-band"]' '1.0.0 · source · '
|
||||
//@ has - '//div[@class="main-heading"]/*[@class="sub-heading"]' '1.0.0'
|
||||
//@ !has - '//div[@class="main-heading"]/*[@class="sub-heading"]' '1.0.0 · source'
|
||||
#[stable(feature = "bar", since = "1.0")]
|
||||
pub fn foo() {}
|
||||
|
||||
//@ has foo/struct.Bar.html
|
||||
//@ has - '//div[@class="main-heading"]/*[@class="out-of-band"]' '1.0.0 · '
|
||||
//@ !has - '//div[@class="main-heading"]/*[@class="out-of-band"]' '1.0.0 · source · '
|
||||
//@ has - '//div[@class="main-heading"]/*[@class="sub-heading"]' '1.0.0'
|
||||
//@ !has - '//div[@class="main-heading"]/*[@class="sub-heading"]' '1.0.0 · source'
|
||||
#[stable(feature = "bar", since = "1.0")]
|
||||
pub struct Bar;
|
||||
|
||||
|
@ -10,15 +10,19 @@ extern crate foo;
|
||||
//@ has - '//a/[@href="struct.DeprecatedStepBy.html"]' "DeprecatedStepBy"
|
||||
//@ has - '//a/[@href="struct.StepBy.html"]' "StepBy"
|
||||
//@ has foo/iter/struct.DeprecatedStepBy.html
|
||||
//@ has - '//h1' "Struct foo::iter::DeprecatedStepBy"
|
||||
//@ has - '//h1' "Struct DeprecatedStepBy"
|
||||
//@ matches - '//*[@class="rustdoc-breadcrumbs"]' 'foo::iter'
|
||||
//@ has foo/iter/struct.StepBy.html
|
||||
//@ has - '//h1' "Struct foo::iter::StepBy"
|
||||
//@ has - '//h1' "Struct StepBy"
|
||||
//@ matches - '//*[@class="rustdoc-breadcrumbs"]' 'foo::iter'
|
||||
|
||||
//@ has bar/iter/index.html
|
||||
//@ has - '//a/[@href="struct.DeprecatedStepBy.html"]' "DeprecatedStepBy"
|
||||
//@ has - '//a/[@href="struct.StepBy.html"]' "StepBy"
|
||||
//@ has bar/iter/struct.DeprecatedStepBy.html
|
||||
//@ has - '//h1' "Struct bar::iter::DeprecatedStepBy"
|
||||
//@ has - '//h1' "Struct DeprecatedStepBy"
|
||||
//@ matches - '//*[@class="rustdoc-breadcrumbs"]' 'bar::iter'
|
||||
//@ has bar/iter/struct.StepBy.html
|
||||
//@ has - '//h1' "Struct bar::iter::StepBy"
|
||||
//@ has - '//h1' "Struct StepBy"
|
||||
//@ matches - '//*[@class="rustdoc-breadcrumbs"]' 'bar::iter'
|
||||
pub use foo::iter;
|
||||
|
@ -6,7 +6,6 @@
|
||||
//@ has foo/index.html '//a[@href="keyword.match.html"]' 'match'
|
||||
//@ has foo/index.html '//div[@class="sidebar-elems"]//li/a' 'Keywords'
|
||||
//@ has foo/index.html '//div[@class="sidebar-elems"]//li/a/@href' '#keywords'
|
||||
//@ has foo/keyword.match.html '//a[@class="keyword"]' 'match'
|
||||
//@ has foo/keyword.match.html '//h1' 'Keyword match'
|
||||
//@ has foo/keyword.match.html '//section[@id="main-content"]//div[@class="docblock"]//p' 'this is a test!'
|
||||
//@ has foo/index.html '//a/@href' '../foo/index.html'
|
||||
|
@ -8,7 +8,6 @@
|
||||
//@ has - '//div[@class="sidebar-elems"]//li/a' 'Primitive Types'
|
||||
//@ has - '//div[@class="sidebar-elems"]//li/a/@href' '#primitives'
|
||||
//@ has foo/primitive.reference.html
|
||||
//@ has - '//a[@class="primitive"]' 'reference'
|
||||
//@ has - '//h1' 'Primitive Type reference'
|
||||
//@ has - '//section[@id="main-content"]//div[@class="docblock"]//p' 'this is a test!'
|
||||
|
||||
|
@ -3,8 +3,7 @@
|
||||
#![crate_name = "foo"]
|
||||
#![feature(rustc_attrs)]
|
||||
|
||||
//@ has foo/primitive.slice.html '//a[@class="primitive"]' 'slice'
|
||||
//@ has - '//h1' 'Primitive Type slice'
|
||||
//@ has foo/primitive.slice.html '//h1' 'Primitive Type slice'
|
||||
//@ has - '//section[@id="main-content"]//div[@class="docblock"]//p' 'this is a test!'
|
||||
//@ has - '//h2[@id="synthetic-implementations"]' 'Auto Trait Implementations'
|
||||
//@ has - '//div[@id="synthetic-implementations-list"]//h3' 'impl<T> Send for [T]where T: Send'
|
||||
|
@ -3,8 +3,7 @@
|
||||
#![crate_name = "foo"]
|
||||
#![feature(rustc_attrs)]
|
||||
|
||||
//@ has foo/primitive.tuple.html '//a[@class="primitive"]' 'tuple'
|
||||
//@ has - '//h1' 'Primitive Type tuple'
|
||||
//@ has foo/primitive.tuple.html '//h1' 'Primitive Type tuple'
|
||||
//@ has - '//section[@id="main-content"]//div[@class="docblock"]//p' 'this is a test!'
|
||||
//@ has - '//h2[@id="synthetic-implementations"]' 'Auto Trait Implementations'
|
||||
//@ has - '//div[@id="synthetic-implementations-list"]//h3' 'Send'
|
||||
|
@ -3,8 +3,7 @@
|
||||
#![crate_name = "foo"]
|
||||
#![feature(rustc_attrs)]
|
||||
|
||||
//@ has foo/primitive.unit.html '//a[@class="primitive"]' 'unit'
|
||||
//@ has - '//h1' 'Primitive Type unit'
|
||||
//@ has foo/primitive.unit.html '//h1' 'Primitive Type unit'
|
||||
//@ has - '//section[@id="main-content"]//div[@class="docblock"]//p' 'this is a test!'
|
||||
//@ has - '//h2[@id="synthetic-implementations"]' 'Auto Trait Implementations'
|
||||
//@ has - '//div[@id="synthetic-implementations-list"]//h3' 'impl Send for ()'
|
||||
|
@ -3,7 +3,7 @@
|
||||
#![feature(staged_api)]
|
||||
|
||||
//@ has foo/trait.Bar.html
|
||||
//@ has - '//div[@class="main-heading"]/*[@class="out-of-band"]' '1.0.0 · source · '
|
||||
//@ has - '//div[@class="main-heading"]/*[@class="sub-heading"]' '1.0.0 · source'
|
||||
#[stable(feature = "bar", since = "1.0")]
|
||||
pub trait Bar {
|
||||
//@ has - '//*[@id="tymethod.foo"]/*[@class="rightside"]' '3.0.0 · source'
|
||||
@ -14,7 +14,7 @@ pub trait Bar {
|
||||
//@ has - '//div[@id="implementors-list"]//*[@class="rightside"]' '4.0.0 · source'
|
||||
|
||||
//@ has foo/struct.Foo.html
|
||||
//@ has - '//div[@class="main-heading"]/*[@class="out-of-band"]' '1.0.0 · source · '
|
||||
//@ has - '//div[@class="main-heading"]/*[@class="sub-heading"]' '1.0.0 · source'
|
||||
#[stable(feature = "baz", since = "1.0")]
|
||||
pub struct Foo;
|
||||
|
||||
|
@ -5,53 +5,65 @@
|
||||
//@ matches 'foo/index.html' '//div[@class="sidebar-crate"]/h2/a' 'foo'
|
||||
//@ count 'foo/index.html' '//h2[@class="location"]' 0
|
||||
|
||||
//@ matches 'foo/foo_mod/index.html' '//h1' 'Module foo::foo_mod'
|
||||
//@ matches 'foo/foo_mod/index.html' '//h2[@class="location"]' 'Module foo_mod'
|
||||
//@ matches 'foo/foo_mod/index.html' '//h1' 'Module foo_mod'
|
||||
//@ matches - '//*[@class="rustdoc-breadcrumbs"]' 'foo'
|
||||
//@ matches - '//h2[@class="location"]' 'Module foo_mod'
|
||||
pub mod foo_mod {
|
||||
pub struct __Thing {}
|
||||
}
|
||||
|
||||
extern "C" {
|
||||
//@ matches 'foo/fn.foo_ffn.html' '//h1' 'Function foo::foo_ffn'
|
||||
//@ matches 'foo/fn.foo_ffn.html' '//h1' 'Function foo_ffn'
|
||||
//@ matches - '//*[@class="rustdoc-breadcrumbs"]' 'foo'
|
||||
pub fn foo_ffn();
|
||||
}
|
||||
|
||||
//@ matches 'foo/fn.foo_fn.html' '//h1' 'Function foo::foo_fn'
|
||||
//@ matches 'foo/fn.foo_fn.html' '//h1' 'Function foo_fn'
|
||||
//@ matches - '//*[@class="rustdoc-breadcrumbs"]' 'foo'
|
||||
pub fn foo_fn() {}
|
||||
|
||||
//@ matches 'foo/trait.FooTrait.html' '//h1' 'Trait foo::FooTrait'
|
||||
//@ matches 'foo/trait.FooTrait.html' '//h2[@class="location"]' 'FooTrait'
|
||||
//@ matches 'foo/trait.FooTrait.html' '//h1' 'Trait FooTrait'
|
||||
//@ matches - '//*[@class="rustdoc-breadcrumbs"]' 'foo'
|
||||
//@ matches - '//h2[@class="location"]' 'FooTrait'
|
||||
pub trait FooTrait {}
|
||||
|
||||
//@ matches 'foo/struct.FooStruct.html' '//h1' 'Struct foo::FooStruct'
|
||||
//@ matches 'foo/struct.FooStruct.html' '//h2[@class="location"]' 'FooStruct'
|
||||
//@ matches 'foo/struct.FooStruct.html' '//h1' 'Struct FooStruct'
|
||||
//@ matches - '//*[@class="rustdoc-breadcrumbs"]' 'foo'
|
||||
//@ matches - '//h2[@class="location"]' 'FooStruct'
|
||||
pub struct FooStruct;
|
||||
|
||||
//@ matches 'foo/enum.FooEnum.html' '//h1' 'Enum foo::FooEnum'
|
||||
//@ matches 'foo/enum.FooEnum.html' '//h2[@class="location"]' 'FooEnum'
|
||||
//@ matches 'foo/enum.FooEnum.html' '//h1' 'Enum FooEnum'
|
||||
//@ matches - '//*[@class="rustdoc-breadcrumbs"]' 'foo'
|
||||
//@ matches - '//h2[@class="location"]' 'FooEnum'
|
||||
pub enum FooEnum {}
|
||||
|
||||
//@ matches 'foo/type.FooType.html' '//h1' 'Type Alias foo::FooType'
|
||||
//@ matches 'foo/type.FooType.html' '//h2[@class="location"]' 'FooType'
|
||||
//@ matches 'foo/type.FooType.html' '//h1' 'Type Alias FooType'
|
||||
//@ matches - '//*[@class="rustdoc-breadcrumbs"]' 'foo'
|
||||
//@ matches - '//h2[@class="location"]' 'FooType'
|
||||
pub type FooType = FooStruct;
|
||||
|
||||
//@ matches 'foo/macro.foo_macro.html' '//h1' 'Macro foo::foo_macro'
|
||||
//@ matches 'foo/macro.foo_macro.html' '//h1' 'Macro foo_macro'
|
||||
//@ matches - '//*[@class="rustdoc-breadcrumbs"]' 'foo'
|
||||
#[macro_export]
|
||||
macro_rules! foo_macro {
|
||||
() => {};
|
||||
}
|
||||
|
||||
//@ matches 'foo/primitive.bool.html' '//h1' 'Primitive Type bool'
|
||||
//@ count - '//*[@class="rustdoc-breadcrumbs"]' 0
|
||||
#[rustc_doc_primitive = "bool"]
|
||||
mod bool {}
|
||||
|
||||
//@ matches 'foo/static.FOO_STATIC.html' '//h1' 'Static foo::FOO_STATIC'
|
||||
//@ matches 'foo/static.FOO_STATIC.html' '//h1' 'Static FOO_STATIC'
|
||||
//@ matches - '//*[@class="rustdoc-breadcrumbs"]' 'foo'
|
||||
pub static FOO_STATIC: FooStruct = FooStruct;
|
||||
|
||||
extern "C" {
|
||||
//@ matches 'foo/static.FOO_FSTATIC.html' '//h1' 'Static foo::FOO_FSTATIC'
|
||||
//@ matches 'foo/static.FOO_FSTATIC.html' '//h1' 'Static FOO_FSTATIC'
|
||||
//@ matches - '//*[@class="rustdoc-breadcrumbs"]' 'foo'
|
||||
pub static FOO_FSTATIC: FooStruct;
|
||||
}
|
||||
|
||||
//@ matches 'foo/constant.FOO_CONSTANT.html' '//h1' 'Constant foo::FOO_CONSTANT'
|
||||
//@ matches 'foo/constant.FOO_CONSTANT.html' '//h1' 'Constant FOO_CONSTANT'
|
||||
//@ matches - '//*[@class="rustdoc-breadcrumbs"]' 'foo'
|
||||
pub const FOO_CONSTANT: FooStruct = FooStruct;
|
||||
|
@ -4,14 +4,14 @@
|
||||
#![crate_name = "foo"]
|
||||
|
||||
//@ has foo/fn.foo.html
|
||||
//@ has - '//div[@class="main-heading"]/*[@class="out-of-band"]' '1.0.0 · '
|
||||
//@ !has - '//div[@class="main-heading"]/*[@class="out-of-band"]' '1.0.0 · source · '
|
||||
//@ has - '//div[@class="main-heading"]/*[@class="sub-heading"]' '1.0.0'
|
||||
//@ !has - '//div[@class="main-heading"]/*[@class="sub-heading"]' '1.0.0 · source'
|
||||
#[stable(feature = "bar", since = "1.0")]
|
||||
pub fn foo() {}
|
||||
|
||||
//@ has foo/struct.Bar.html
|
||||
//@ has - '//div[@class="main-heading"]/*[@class="out-of-band"]' '1.0.0 · '
|
||||
//@ !has - '//div[@class="main-heading"]/*[@class="out-of-band"]' '1.0.0 · source · '
|
||||
//@ has - '//div[@class="main-heading"]/*[@class="sub-heading"]' '1.0.0'
|
||||
//@ !has - '//div[@class="main-heading"]/*[@class="sub-heading"]' '1.0.0 · source'
|
||||
#[stable(feature = "bar", since = "1.0")]
|
||||
pub struct Bar;
|
||||
|
||||
|
@ -1,6 +1,3 @@
|
||||
#![feature(const_intrinsic_copy)]
|
||||
|
||||
|
||||
const MISALIGNED_LOAD: () = unsafe {
|
||||
let mem = [0u32; 8];
|
||||
let ptr = mem.as_ptr().byte_add(1);
|
||||
|
@ -1,11 +1,11 @@
|
||||
error[E0080]: evaluation of constant value failed
|
||||
--> $DIR/raw-pointer-ub.rs:7:16
|
||||
--> $DIR/raw-pointer-ub.rs:4:16
|
||||
|
|
||||
LL | let _val = *ptr;
|
||||
| ^^^^ accessing memory based on pointer with alignment 1, but alignment 4 is required
|
||||
|
||||
error[E0080]: evaluation of constant value failed
|
||||
--> $DIR/raw-pointer-ub.rs:14:5
|
||||
--> $DIR/raw-pointer-ub.rs:11:5
|
||||
|
|
||||
LL | *ptr = 0;
|
||||
| ^^^^^^^^ accessing memory based on pointer with alignment 1, but alignment 4 is required
|
||||
@ -20,19 +20,19 @@ note: inside `copy_nonoverlapping::<u32>`
|
||||
note: inside `std::ptr::const_ptr::<impl *const u32>::copy_to_nonoverlapping`
|
||||
--> $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL
|
||||
note: inside `MISALIGNED_COPY`
|
||||
--> $DIR/raw-pointer-ub.rs:22:5
|
||||
--> $DIR/raw-pointer-ub.rs:19:5
|
||||
|
|
||||
LL | y.copy_to_nonoverlapping(&mut z, 1);
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
error[E0080]: evaluation of constant value failed
|
||||
--> $DIR/raw-pointer-ub.rs:34:16
|
||||
--> $DIR/raw-pointer-ub.rs:31:16
|
||||
|
|
||||
LL | let _val = (*ptr).0;
|
||||
| ^^^^^^^^ accessing memory based on pointer with alignment 4, but alignment 16 is required
|
||||
|
||||
error[E0080]: evaluation of constant value failed
|
||||
--> $DIR/raw-pointer-ub.rs:41:16
|
||||
--> $DIR/raw-pointer-ub.rs:38:16
|
||||
|
|
||||
LL | let _val = *ptr;
|
||||
| ^^^^ memory access failed: expected a pointer to 8 bytes of memory, but got ALLOC0 which is only 4 bytes from the end of the allocation
|
||||
|
@ -1,20 +0,0 @@
|
||||
// Regression test for #130310
|
||||
// Tests that we do not fall into infinite
|
||||
// recursion while checking FFI safety of
|
||||
// recursive types like `A<T>` below
|
||||
|
||||
//@ build-pass
|
||||
use std::marker::PhantomData;
|
||||
|
||||
#[repr(C)]
|
||||
struct A<T> {
|
||||
a: *const A<A<T>>, // Recursive because of this field
|
||||
p: PhantomData<T>,
|
||||
}
|
||||
|
||||
extern "C" {
|
||||
fn f(a: *const A<()>);
|
||||
//~^ WARN `extern` block uses type `*const A<()>`, which is not FFI-safe
|
||||
}
|
||||
|
||||
fn main() {}
|
@ -1,11 +0,0 @@
|
||||
warning: `extern` block uses type `*const A<()>`, which is not FFI-safe
|
||||
--> $DIR/improper-types-stack-overflow-130310.rs:16:13
|
||||
|
|
||||
LL | fn f(a: *const A<()>);
|
||||
| ^^^^^^^^^^^^ not FFI-safe
|
||||
|
|
||||
= note: type is infinitely recursive
|
||||
= note: `#[warn(improper_ctypes)]` on by default
|
||||
|
||||
warning: 1 warning emitted
|
||||
|
32
tests/ui/lint/lint-ctypes-non-recursion-limit.rs
Normal file
32
tests/ui/lint/lint-ctypes-non-recursion-limit.rs
Normal file
@ -0,0 +1,32 @@
|
||||
//@ check-pass
|
||||
|
||||
#![recursion_limit = "5"]
|
||||
#![allow(unused)]
|
||||
#![deny(improper_ctypes)]
|
||||
|
||||
#[repr(C)]
|
||||
struct F1(*const ());
|
||||
#[repr(C)]
|
||||
struct F2(*const ());
|
||||
#[repr(C)]
|
||||
struct F3(*const ());
|
||||
#[repr(C)]
|
||||
struct F4(*const ());
|
||||
#[repr(C)]
|
||||
struct F5(*const ());
|
||||
#[repr(C)]
|
||||
struct F6(*const ());
|
||||
|
||||
#[repr(C)]
|
||||
struct B {
|
||||
f1: F1,
|
||||
f2: F2,
|
||||
f3: F3,
|
||||
f4: F4,
|
||||
f5: F5,
|
||||
f6: F6,
|
||||
}
|
||||
|
||||
extern "C" fn foo(_: B) {}
|
||||
|
||||
fn main() {}
|
Loading…
Reference in New Issue
Block a user