Auto merge of #104990 - matthiaskrgr:rollup-oskk8v3, r=matthiaskrgr

Rollup of 4 pull requests

Successful merges:

 - #104955 (Switch rustdoc-gui test to function call)
 - #104976 (Prefer doc comments over `//`-comments in compiler)
 - #104984 (Remove Crate::primitives field)
 - #104989 (update Miri)

Failed merges:

r? `@ghost`
`@rustbot` modify labels: rollup
This commit is contained in:
bors 2022-11-28 00:18:22 +00:00
commit 8c6bf2bee7
169 changed files with 1343 additions and 909 deletions

View file

@ -111,8 +111,8 @@ impl<CTX: rustc_span::HashStableContext> HashStable<CTX> for Path {
}
impl Path {
// Convert a span and an identifier to the corresponding
// one-segment path.
/// Convert a span and an identifier to the corresponding
/// one-segment path.
pub fn from_ident(ident: Ident) -> Path {
Path { segments: thin_vec![PathSegment::from_ident(ident)], span: ident.span, tokens: None }
}
@ -1283,7 +1283,7 @@ impl Expr {
)
}
// To a first-order approximation, is this a pattern
/// To a first-order approximation, is this a pattern?
pub fn is_approximately_pattern(&self) -> bool {
match &self.peel_parens().kind {
ExprKind::Box(_)

View file

@ -26,9 +26,9 @@ use thin_vec::thin_vec;
pub struct MarkedAttrs(GrowableBitSet<AttrId>);
impl MarkedAttrs {
// We have no idea how many attributes there will be, so just
// initiate the vectors with 0 bits. We'll grow them as necessary.
pub fn new() -> Self {
// We have no idea how many attributes there will be, so just
// initiate the vectors with 0 bits. We'll grow them as necessary.
MarkedAttrs(GrowableBitSet::new_empty())
}
@ -174,9 +174,11 @@ impl MetaItem {
self.ident().unwrap_or_else(Ident::empty).name
}
// Example:
// #[attribute(name = "value")]
// ^^^^^^^^^^^^^^
/// ```text
/// Example:
/// #[attribute(name = "value")]
/// ^^^^^^^^^^^^^^
/// ```
pub fn name_value_literal(&self) -> Option<&Lit> {
match &self.kind {
MetaItemKind::NameValue(v) => Some(v),

View file

@ -725,10 +725,10 @@ pub fn visit_lazy_tts<T: MutVisitor>(lazy_tts: &mut Option<LazyAttrTokenStream>,
visit_lazy_tts_opt_mut(lazy_tts.as_mut(), vis);
}
/// Applies ident visitor if it's an ident; applies other visits to interpolated nodes.
/// In practice the ident part is not actually used by specific visitors right now,
/// but there's a test below checking that it works.
// No `noop_` prefix because there isn't a corresponding method in `MutVisitor`.
// Applies ident visitor if it's an ident; applies other visits to interpolated nodes.
// In practice the ident part is not actually used by specific visitors right now,
// but there's a test below checking that it works.
pub fn visit_token<T: MutVisitor>(t: &mut Token, vis: &mut T) {
let Token { kind, span } = t;
match kind {

View file

@ -302,9 +302,9 @@ impl TokenKind {
Literal(Lit::new(kind, symbol, suffix))
}
// An approximation to proc-macro-style single-character operators used by rustc parser.
// If the operator token can be broken into two tokens, the first of which is single-character,
// then this function performs that operation, otherwise it returns `None`.
/// An approximation to proc-macro-style single-character operators used by rustc parser.
/// If the operator token can be broken into two tokens, the first of which is single-character,
/// then this function performs that operation, otherwise it returns `None`.
pub fn break_two_token_op(&self) -> Option<(TokenKind, TokenKind)> {
Some(match *self {
Le => (Lt, Eq),
@ -538,10 +538,10 @@ impl Token {
}
}
// A convenience function for matching on identifiers during parsing.
// Turns interpolated identifier (`$i: ident`) or lifetime (`$l: lifetime`) token
// into the regular identifier or lifetime token it refers to,
// otherwise returns the original token.
/// A convenience function for matching on identifiers during parsing.
/// Turns interpolated identifier (`$i: ident`) or lifetime (`$l: lifetime`) token
/// into the regular identifier or lifetime token it refers to,
/// otherwise returns the original token.
pub fn uninterpolate(&self) -> Cow<'_, Token> {
match &self.kind {
Interpolated(nt) => match **nt {
@ -621,7 +621,7 @@ impl Token {
false
}
// Is the token an interpolated block (`$b:block`)?
/// Is the token an interpolated block (`$b:block`)?
pub fn is_whole_block(&self) -> bool {
if let Interpolated(nt) = &self.kind && let NtBlock(..) = **nt {
return true;
@ -665,8 +665,8 @@ impl Token {
self.is_non_raw_ident_where(Ident::is_path_segment_keyword)
}
// Returns true for reserved identifiers used internally for elided lifetimes,
// unnamed method parameters, crate root module, error recovery etc.
/// Returns true for reserved identifiers used internally for elided lifetimes,
/// unnamed method parameters, crate root module, error recovery etc.
pub fn is_special_ident(&self) -> bool {
self.is_non_raw_ident_where(Ident::is_special)
}

View file

@ -86,12 +86,12 @@ impl TokenTree {
}
}
// Create a `TokenTree::Token` with alone spacing.
/// Create a `TokenTree::Token` with alone spacing.
pub fn token_alone(kind: TokenKind, span: Span) -> TokenTree {
TokenTree::Token(Token::new(kind, span), Spacing::Alone)
}
// Create a `TokenTree::Token` with joint spacing.
/// Create a `TokenTree::Token` with joint spacing.
pub fn token_joint(kind: TokenKind, span: Span) -> TokenTree {
TokenTree::Token(Token::new(kind, span), Spacing::Joint)
}
@ -413,17 +413,17 @@ impl TokenStream {
TokenStream(Lrc::new(self.0.iter().enumerate().map(|(i, tree)| f(i, tree)).collect()))
}
// Create a token stream containing a single token with alone spacing.
/// Create a token stream containing a single token with alone spacing.
pub fn token_alone(kind: TokenKind, span: Span) -> TokenStream {
TokenStream::new(vec![TokenTree::token_alone(kind, span)])
}
// Create a token stream containing a single token with joint spacing.
/// Create a token stream containing a single token with joint spacing.
pub fn token_joint(kind: TokenKind, span: Span) -> TokenStream {
TokenStream::new(vec![TokenTree::token_joint(kind, span)])
}
// Create a token stream containing a single `Delimited`.
/// Create a token stream containing a single `Delimited`.
pub fn delimited(span: DelimSpan, delim: Delimiter, tts: TokenStream) -> TokenStream {
TokenStream::new(vec![TokenTree::Delimited(span, delim, tts)])
}
@ -522,8 +522,8 @@ impl TokenStream {
}
}
// Push `tt` onto the end of the stream, possibly gluing it to the last
// token. Uses `make_mut` to maximize efficiency.
/// Push `tt` onto the end of the stream, possibly gluing it to the last
/// token. Uses `make_mut` to maximize efficiency.
pub fn push_tree(&mut self, tt: TokenTree) {
let vec_mut = Lrc::make_mut(&mut self.0);
@ -534,9 +534,9 @@ impl TokenStream {
}
}
// Push `stream` onto the end of the stream, possibly gluing the first
// token tree to the last token. (No other token trees will be glued.)
// Uses `make_mut` to maximize efficiency.
/// Push `stream` onto the end of the stream, possibly gluing the first
/// token tree to the last token. (No other token trees will be glued.)
/// Uses `make_mut` to maximize efficiency.
pub fn push_stream(&mut self, stream: TokenStream) {
let vec_mut = Lrc::make_mut(&mut self.0);

View file

@ -36,8 +36,8 @@ impl Printer {
self.nbsp()
}
// Synthesizes a comment that was not textually present in the original
// source file.
/// Synthesizes a comment that was not textually present in the original
/// source file.
pub fn synth_comment(&mut self, text: impl Into<Cow<'static, str>>) {
self.word("/*");
self.space();

View file

@ -58,10 +58,10 @@ impl<'a> State<'a> {
self.print_expr_cond_paren(expr, Self::cond_needs_par(expr))
}
// Does `expr` need parentheses when printed in a condition position?
//
// These cases need parens due to the parse error observed in #26461: `if return {}`
// parses as the erroneous construct `if (return {})`, not `if (return) {}`.
/// Does `expr` need parentheses when printed in a condition position?
///
/// These cases need parens due to the parse error observed in #26461: `if return {}`
/// parses as the erroneous construct `if (return {})`, not `if (return) {}`.
pub(super) fn cond_needs_par(expr: &ast::Expr) -> bool {
match expr.kind {
ast::ExprKind::Break(..)

View file

@ -41,7 +41,7 @@ pub(crate) struct IncorrectMetaItem {
pub span: Span,
}
// Error code: E0541
/// Error code: E0541
pub(crate) struct UnknownMetaItem<'a> {
pub span: Span,
pub item: String,
@ -200,7 +200,7 @@ pub(crate) struct InvalidReprHintNoValue {
pub name: String,
}
// Error code: E0565
/// Error code: E0565
pub(crate) struct UnsupportedLiteral {
pub span: Span,
pub reason: UnsupportedLiteralReason,

View file

@ -590,7 +590,7 @@ impl UseSpans<'_> {
}
}
// Add a span label to the arguments of the closure, if it exists.
/// Add a span label to the arguments of the closure, if it exists.
pub(super) fn args_span_label(self, err: &mut Diagnostic, message: impl Into<String>) {
if let UseSpans::ClosureUse { args_span, .. } = self {
err.span_label(args_span, message);
@ -628,7 +628,7 @@ impl UseSpans<'_> {
}
}
// Add a span label to the use of the captured variable, if it exists.
/// Add a span label to the use of the captured variable, if it exists.
pub(super) fn var_span_label(
self,
err: &mut Diagnostic,

View file

@ -83,7 +83,7 @@ mod type_check;
mod universal_regions;
mod used_muts;
// A public API provided for the Rust compiler consumers.
/// A public API provided for the Rust compiler consumers.
pub mod consumers;
use borrow_set::{BorrowData, BorrowSet};

View file

@ -121,8 +121,8 @@ pub(super) fn populate_access_facts<'a, 'tcx>(
}
}
// For every potentially drop()-touched region `region` in `local`'s type
// (`kind`), emit a Polonius `use_of_var_derefs_origin(local, origin)` fact.
/// For every potentially drop()-touched region `region` in `local`'s type
/// (`kind`), emit a Polonius `use_of_var_derefs_origin(local, origin)` fact.
pub(super) fn add_drop_of_var_derefs_origin<'tcx>(
typeck: &mut TypeChecker<'_, 'tcx>,
local: Local,

View file

@ -300,12 +300,12 @@ struct TypeParameter {
ty: P<ast::Ty>,
}
// The code snippets built up for derived code are sometimes used as blocks
// (e.g. in a function body) and sometimes used as expressions (e.g. in a match
// arm). This structure avoids committing to either form until necessary,
// avoiding the insertion of any unnecessary blocks.
//
// The statements come before the expression.
/// The code snippets built up for derived code are sometimes used as blocks
/// (e.g. in a function body) and sometimes used as expressions (e.g. in a match
/// arm). This structure avoids committing to either form until necessary,
/// avoiding the insertion of any unnecessary blocks.
///
/// The statements come before the expression.
pub struct BlockOrExpr(Vec<ast::Stmt>, Option<P<Expr>>);
impl BlockOrExpr {

View file

@ -6,15 +6,15 @@ use rustc_span::edition::Edition;
use rustc_span::symbol::sym;
use rustc_span::Span;
// This expands to either
// - `$crate::panic::panic_2015!(...)` or
// - `$crate::panic::panic_2021!(...)`
// depending on the edition.
//
// This is used for both std::panic!() and core::panic!().
//
// `$crate` will refer to either the `std` or `core` crate depending on which
// one we're expanding from.
/// This expands to either
/// - `$crate::panic::panic_2015!(...)` or
/// - `$crate::panic::panic_2021!(...)`
/// depending on the edition.
///
/// This is used for both std::panic!() and core::panic!().
///
/// `$crate` will refer to either the `std` or `core` crate depending on which
/// one we're expanding from.
pub fn expand_panic<'cx>(
cx: &'cx mut ExtCtxt<'_>,
sp: Span,
@ -24,10 +24,10 @@ pub fn expand_panic<'cx>(
expand(mac, cx, sp, tts)
}
// This expands to either
// - `$crate::panic::unreachable_2015!(...)` or
// - `$crate::panic::unreachable_2021!(...)`
// depending on the edition.
/// This expands to either
/// - `$crate::panic::unreachable_2015!(...)` or
/// - `$crate::panic::unreachable_2021!(...)`
/// depending on the edition.
pub fn expand_unreachable<'cx>(
cx: &'cx mut ExtCtxt<'_>,
sp: Span,

View file

@ -164,7 +164,7 @@ pub fn expand_include<'cx>(
Box::new(ExpandResult { p, node_id: cx.current_expansion.lint_node_id })
}
// include_str! : read the given file, insert it as a literal string expr
/// `include_str!`: read the given file, insert it as a literal string expr
pub fn expand_include_str(
cx: &mut ExtCtxt<'_>,
sp: Span,

View file

@ -13,13 +13,13 @@ use rustc_span::Span;
use std::iter;
use thin_vec::thin_vec;
// #[test_case] is used by custom test authors to mark tests
// When building for test, it needs to make the item public and gensym the name
// Otherwise, we'll omit the item. This behavior means that any item annotated
// with #[test_case] is never addressable.
//
// We mark item with an inert attribute "rustc_test_marker" which the test generation
// logic will pick up on.
/// #[test_case] is used by custom test authors to mark tests
/// When building for test, it needs to make the item public and gensym the name
/// Otherwise, we'll omit the item. This behavior means that any item annotated
/// with #[test_case] is never addressable.
///
/// We mark item with an inert attribute "rustc_test_marker" which the test generation
/// logic will pick up on.
pub fn expand_test_case(
ecx: &mut ExtCtxt<'_>,
attr_sp: Span,

View file

@ -34,8 +34,8 @@ struct TestCtxt<'a> {
test_runner: Option<ast::Path>,
}
// Traverse the crate, collecting all the test functions, eliding any
// existing main functions, and synthesizing a main test harness
/// Traverse the crate, collecting all the test functions, eliding any
/// existing main functions, and synthesizing a main test harness
pub fn inject(sess: &Session, resolver: &mut dyn ResolverExpand, krate: &mut ast::Crate) {
let span_diagnostic = sess.diagnostic();
let panic_strategy = sess.panic_strategy();

View file

@ -108,8 +108,8 @@ impl<'tcx> CValue<'tcx> {
}
// FIXME remove
// Forces the data value of a dyn* value to the stack and returns a pointer to it as well as the
// vtable pointer.
/// Forces the data value of a dyn* value to the stack and returns a pointer to it as well as the
/// vtable pointer.
pub(crate) fn dyn_star_force_data_on_stack(
self,
fx: &mut FunctionCx<'_, '_, 'tcx>,

View file

@ -88,9 +88,9 @@ pub struct CodegenCx<'gcc, 'tcx> {
pub vtables: RefCell<FxHashMap<(Ty<'tcx>, Option<ty::PolyExistentialTraitRef<'tcx>>), RValue<'gcc>>>,
// TODO(antoyo): improve the SSA API to not require those.
// Mapping from function pointer type to indexes of on stack parameters.
/// Mapping from function pointer type to indexes of on stack parameters.
pub on_stack_params: RefCell<FxHashMap<FunctionPtrType<'gcc>, FxHashSet<usize>>>,
// Mapping from function to indexes of on stack parameters.
/// Mapping from function to indexes of on stack parameters.
pub on_stack_function_params: RefCell<FxHashMap<Function<'gcc>, FxHashSet<usize>>>,
/// Cache of emitted const globals (value -> global)

View file

@ -37,7 +37,7 @@ const VAR_ALIGN_BYTES: usize = 8;
/// A context object for maintaining all state needed by the coverageinfo module.
pub struct CrateCoverageContext<'ll, 'tcx> {
// Coverage data for each instrumented function identified by DefId.
/// Coverage data for each instrumented function identified by DefId.
pub(crate) function_coverage_map: RefCell<FxHashMap<Instance<'tcx>, FunctionCoverage<'tcx>>>,
pub(crate) pgo_func_name_var_map: RefCell<FxHashMap<Instance<'tcx>, &'ll llvm::Value>>,
}

View file

@ -35,7 +35,7 @@ pub enum LLVMRustResult {
pub struct LLVMRustCOFFShortExport {
pub name: *const c_char,
pub ordinal_present: bool,
// value of `ordinal` only important when `ordinal_present` is true
/// value of `ordinal` only important when `ordinal_present` is true
pub ordinal: u16,
}

View file

@ -194,8 +194,8 @@ pub fn to_llvm_features<'a>(sess: &Session, s: &'a str) -> SmallVec<[&'a str; 2]
}
}
// Given a map from target_features to whether they are enabled or disabled,
// ensure only valid combinations are allowed.
/// Given a map from target_features to whether they are enabled or disabled,
/// ensure only valid combinations are allowed.
pub fn check_tied_features(
sess: &Session,
features: &FxHashMap<&str, bool>,
@ -213,8 +213,8 @@ pub fn check_tied_features(
return None;
}
// Used to generate cfg variables and apply features
// Must express features in the way Rust understands them
/// Used to generate cfg variables and apply features
/// Must express features in the way Rust understands them
pub fn target_features(sess: &Session, allow_unstable: bool) -> Vec<Symbol> {
let target_machine = create_informational_target_machine(sess);
let mut features: Vec<Symbol> = supported_target_features(sess)

View file

@ -238,7 +238,7 @@ impl Type {
unsafe { llvm::LLVMInt8TypeInContext(llcx) }
}
// Creates an integer type with the given number of bits, e.g., i24
/// Creates an integer type with the given number of bits, e.g., i24
pub fn ix_llcx(llcx: &llvm::Context, num_bits: u64) -> &Type {
unsafe { llvm::LLVMIntTypeInContext(llcx, num_bits as c_uint) }
}

View file

@ -1179,7 +1179,7 @@ pub fn ignored_for_lto(sess: &Session, info: &CrateInfo, cnum: CrateNum) -> bool
&& (info.compiler_builtins == Some(cnum) || info.is_no_builtins.contains(&cnum))
}
// This functions tries to determine the appropriate linker (and corresponding LinkerFlavor) to use
/// This functions tries to determine the appropriate linker (and corresponding LinkerFlavor) to use
pub fn linker_and_flavor(sess: &Session) -> (PathBuf, LinkerFlavor) {
fn infer_from(
sess: &Session,

View file

@ -34,9 +34,9 @@ pub fn disable_localization(linker: &mut Command) {
linker.env("VSLANG", "1033");
}
// The third parameter is for env vars, used on windows to set up the
// path for MSVC to find its DLLs, and gcc to find its bundled
// toolchain
/// The third parameter is for env vars, used on windows to set up the
/// path for MSVC to find its DLLs, and gcc to find its bundled
/// toolchain
pub fn get_linker<'a>(
sess: &'a Session,
linker: &Path,

View file

@ -191,38 +191,38 @@ pub enum MetadataPosition {
Last,
}
// For rlibs we "pack" rustc metadata into a dummy object file.
//
// Historically it was needed because rustc linked rlibs as whole-archive in some cases.
// In that case linkers try to include all files located in an archive, so if metadata is stored
// in an archive then it needs to be of a form that the linker is able to process.
// Now it's not clear whether metadata still needs to be wrapped into an object file or not.
//
// Note, though, that we don't actually want this metadata to show up in any
// final output of the compiler. Instead this is purely for rustc's own
// metadata tracking purposes.
//
// With the above in mind, each "flavor" of object format gets special
// handling here depending on the target:
//
// * MachO - macos-like targets will insert the metadata into a section that
// is sort of fake dwarf debug info. Inspecting the source of the macos
// linker this causes these sections to be skipped automatically because
// it's not in an allowlist of otherwise well known dwarf section names to
// go into the final artifact.
//
// * WebAssembly - we actually don't have any container format for this
// target. WebAssembly doesn't support the `dylib` crate type anyway so
// there's no need for us to support this at this time. Consequently the
// metadata bytes are simply stored as-is into an rlib.
//
// * COFF - Windows-like targets create an object with a section that has
// the `IMAGE_SCN_LNK_REMOVE` flag set which ensures that if the linker
// ever sees the section it doesn't process it and it's removed.
//
// * ELF - All other targets are similar to Windows in that there's a
// `SHF_EXCLUDE` flag we can set on sections in an object file to get
// automatically removed from the final output.
/// For rlibs we "pack" rustc metadata into a dummy object file.
///
/// Historically it was needed because rustc linked rlibs as whole-archive in some cases.
/// In that case linkers try to include all files located in an archive, so if metadata is stored
/// in an archive then it needs to be of a form that the linker is able to process.
/// Now it's not clear whether metadata still needs to be wrapped into an object file or not.
///
/// Note, though, that we don't actually want this metadata to show up in any
/// final output of the compiler. Instead this is purely for rustc's own
/// metadata tracking purposes.
///
/// With the above in mind, each "flavor" of object format gets special
/// handling here depending on the target:
///
/// * MachO - macos-like targets will insert the metadata into a section that
/// is sort of fake dwarf debug info. Inspecting the source of the macos
/// linker this causes these sections to be skipped automatically because
/// it's not in an allowlist of otherwise well known dwarf section names to
/// go into the final artifact.
///
/// * WebAssembly - we actually don't have any container format for this
/// target. WebAssembly doesn't support the `dylib` crate type anyway so
/// there's no need for us to support this at this time. Consequently the
/// metadata bytes are simply stored as-is into an rlib.
///
/// * COFF - Windows-like targets create an object with a section that has
/// the `IMAGE_SCN_LNK_REMOVE` flag set which ensures that if the linker
/// ever sees the section it doesn't process it and it's removed.
///
/// * ELF - All other targets are similar to Windows in that there's a
/// `SHF_EXCLUDE` flag we can set on sections in an object file to get
/// automatically removed from the final output.
pub fn create_wrapper_file(
sess: &Session,
section_name: Vec<u8>,

View file

@ -340,20 +340,20 @@ pub struct CodegenContext<B: WriteBackendMethods> {
pub split_debuginfo: rustc_target::spec::SplitDebuginfo,
pub split_dwarf_kind: rustc_session::config::SplitDwarfKind,
// Number of cgus excluding the allocator/metadata modules
/// Number of cgus excluding the allocator/metadata modules
pub total_cgus: usize,
// Handler to use for diagnostics produced during codegen.
/// Handler to use for diagnostics produced during codegen.
pub diag_emitter: SharedEmitter,
// LLVM optimizations for which we want to print remarks.
/// LLVM optimizations for which we want to print remarks.
pub remark: Passes,
// Worker thread number
/// Worker thread number
pub worker: usize,
// The incremental compilation session directory, or None if we are not
// compiling incrementally
/// The incremental compilation session directory, or None if we are not
/// compiling incrementally
pub incr_comp_session_dir: Option<PathBuf>,
// Used to update CGU re-use information during the thinlto phase.
/// Used to update CGU re-use information during the thinlto phase.
pub cgu_reuse_tracker: CguReuseTracker,
// Channel back to the main control thread to send messages to
/// Channel back to the main control thread to send messages to
pub coordinator_send: Sender<Box<dyn Any + Send>>,
}
@ -756,7 +756,7 @@ fn execute_work_item<B: ExtraBackendMethods>(
}
}
// Actual LTO type we end up choosing based on multiple factors.
/// Actual LTO type we end up choosing based on multiple factors.
pub enum ComputedLtoType {
No,
Thin,

View file

@ -1,4 +1,4 @@
// Type Names for Debug Info.
//! Type Names for Debug Info.
// Notes on targeting MSVC:
// In general, MSVC's debugger attempts to parse all arguments as C++ expressions,
@ -26,10 +26,10 @@ use std::fmt::Write;
use crate::debuginfo::wants_c_like_enum_debuginfo;
// Compute the name of the type as it should be stored in debuginfo. Does not do
// any caching, i.e., calling the function twice with the same type will also do
// the work twice. The `qualified` parameter only affects the first level of the
// type name, further levels (i.e., type parameters) are always fully qualified.
/// Compute the name of the type as it should be stored in debuginfo. Does not do
/// any caching, i.e., calling the function twice with the same type will also do
/// the work twice. The `qualified` parameter only affects the first level of the
/// type name, further levels (i.e., type parameters) are always fully qualified.
pub fn compute_debuginfo_type_name<'tcx>(
tcx: TyCtxt<'tcx>,
t: Ty<'tcx>,

View file

@ -40,10 +40,10 @@ pub enum OperandValue<V> {
/// instead.
#[derive(Copy, Clone)]
pub struct OperandRef<'tcx, V> {
// The value.
/// The value.
pub val: OperandValue<V>,
// The layout of value, based on its Rust type.
/// The layout of value, based on its Rust type.
pub layout: TyAndLayout<'tcx>,
}

View file

@ -417,8 +417,8 @@ pub trait Machine<'mir, 'tcx>: Sized {
}
}
// A lot of the flexibility above is just needed for `Miri`, but all "compile-time" machines
// (CTFE and ConstProp) use the same instance. Here, we share that code.
/// A lot of the flexibility above is just needed for `Miri`, but all "compile-time" machines
/// (CTFE and ConstProp) use the same instance. Here, we share that code.
pub macro compile_time_machine(<$mir: lifetime, $tcx: lifetime>) {
type Provenance = AllocId;
type ProvenanceExtra = ();

View file

@ -206,8 +206,8 @@ where
}
}
// Iterates over all fields of an array. Much more efficient than doing the
// same by repeatedly calling `operand_index`.
/// Iterates over all fields of an array. Much more efficient than doing the
/// same by repeatedly calling `operand_index`.
pub fn operand_array_fields<'a>(
&self,
base: &'a OpTy<'tcx, Prov>,

View file

@ -324,7 +324,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> ValueMut<'mir, 'tcx, M>
macro_rules! make_value_visitor {
($visitor_trait:ident, $value_trait:ident, $($mutability:ident)?) => {
// How to traverse a value and what to do when we are at the leaves.
/// How to traverse a value and what to do when we are at the leaves.
pub trait $visitor_trait<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>>: Sized {
type V: $value_trait<'mir, 'tcx, M>;

View file

@ -75,14 +75,14 @@ pub fn rustc_allow_const_fn_unstable(
attr::rustc_allow_const_fn_unstable(&tcx.sess, attrs).any(|name| name == feature_gate)
}
// Returns `true` if the given `const fn` is "const-stable".
//
// Panics if the given `DefId` does not refer to a `const fn`.
//
// Const-stability is only relevant for `const fn` within a `staged_api` crate. Only "const-stable"
// functions can be called in a const-context by users of the stable compiler. "const-stable"
// functions are subject to more stringent restrictions than "const-unstable" functions: They
// cannot use unstable features and can only call other "const-stable" functions.
/// Returns `true` if the given `const fn` is "const-stable".
///
/// Panics if the given `DefId` does not refer to a `const fn`.
///
/// Const-stability is only relevant for `const fn` within a `staged_api` crate. Only "const-stable"
/// functions can be called in a const-context by users of the stable compiler. "const-stable"
/// functions are subject to more stringent restrictions than "const-unstable" functions: They
/// cannot use unstable features and can only call other "const-stable" functions.
pub fn is_const_stable_const_fn(tcx: TyCtxt<'_>, def_id: DefId) -> bool {
// A default body in a `#[const_trait]` is not const-stable because const
// trait fns currently cannot be const-stable. We shouldn't

View file

@ -686,7 +686,7 @@ impl<'tcx> NonConstOp<'tcx> for ThreadLocalAccess {
}
}
// Types that cannot appear in the signature or locals of a `const fn`.
/// Types that cannot appear in the signature or locals of a `const fn`.
pub mod ty {
use super::*;

View file

@ -9,10 +9,11 @@ use std::iter::TrustedLen;
/// Expand `lhs = Rvalue::Aggregate(kind, operands)` into assignments to the fields.
///
/// Produces something like
///
/// ```ignore (ilustrative)
/// (lhs as Variant).field0 = arg0; // We only have a downcast if this is an enum
/// (lhs as Variant).field1 = arg1;
/// discriminant(lhs) = variant_index; // If lhs is an enum or generator.
/// ```
pub fn expand_aggregate<'tcx>(
orig_lhs: Place<'tcx>,
operands: impl Iterator<Item = (Operand<'tcx>, Ty<'tcx>)> + TrustedLen,

View file

@ -1336,8 +1336,8 @@ mod signal_handler {
}
}
// When an error signal (such as SIGABRT or SIGSEGV) is delivered to the
// process, print a stack trace and then exit.
/// When an error signal (such as SIGABRT or SIGSEGV) is delivered to the
/// process, print a stack trace and then exit.
pub(super) fn install() {
unsafe {
const ALT_STACK_SIZE: usize = libc::MINSIGSTKSZ + 64 * 1024;

View file

@ -242,8 +242,8 @@ pub enum ExpandResult<T, U> {
Retry(U),
}
// `meta_item` is the attribute, and `item` is the item being modified.
pub trait MultiItemModifier {
/// `meta_item` is the attribute, and `item` is the item being modified.
fn expand(
&self,
ecx: &mut ExtCtxt<'_>,

View file

@ -193,7 +193,7 @@ impl<'a> ExtCtxt<'a> {
self.stmt_local(local, sp)
}
// Generates `let _: Type;`, which is usually used for type assertions.
/// Generates `let _: Type;`, which is usually used for type assertions.
pub fn stmt_let_type_only(&self, span: Span, ty: P<ast::Ty>) -> ast::Stmt {
let local = P(ast::Local {
pat: self.pat_wild(span),

View file

@ -200,7 +200,7 @@ fn get_features(
features
}
// `cfg_attr`-process the crate's attributes and compute the crate's features.
/// `cfg_attr`-process the crate's attributes and compute the crate's features.
pub fn features(
sess: &Session,
mut krate: ast::Crate,

View file

@ -401,7 +401,7 @@ impl<'a, 'b> MacroExpander<'a, 'b> {
krate
}
// Recursively expand all macro invocations in this AST fragment.
/// Recursively expand all macro invocations in this AST fragment.
pub fn fully_expand_fragment(&mut self, input_fragment: AstFragment) -> AstFragment {
let orig_expansion_data = self.cx.current_expansion.clone();
let orig_force_mode = self.cx.force_mode;
@ -1931,9 +1931,12 @@ pub struct ExpansionConfig<'feat> {
pub features: Option<&'feat Features>,
pub recursion_limit: Limit,
pub trace_mac: bool,
pub should_test: bool, // If false, strip `#[test]` nodes
pub span_debug: bool, // If true, use verbose debugging for `proc_macro::Span`
pub proc_macro_backtrace: bool, // If true, show backtraces for proc-macro panics
/// If false, strip `#[test]` nodes
pub should_test: bool,
/// If true, use verbose debugging for `proc_macro::Span`
pub span_debug: bool,
/// If true, show backtraces for proc-macro panics
pub proc_macro_backtrace: bool,
}
impl<'feat> ExpansionConfig<'feat> {

View file

@ -981,8 +981,8 @@ pub struct Pat<'hir> {
pub hir_id: HirId,
pub kind: PatKind<'hir>,
pub span: Span,
// Whether to use default binding modes.
// At present, this is false only for destructuring assignment.
/// Whether to use default binding modes.
/// At present, this is false only for destructuring assignment.
pub default_binding_modes: bool,
}
@ -1090,7 +1090,7 @@ impl fmt::Display for RangeEnd {
pub struct DotDotPos(u32);
impl DotDotPos {
// Panics if n >= u32::MAX.
/// Panics if n >= u32::MAX.
pub fn new(n: Option<usize>) -> Self {
match n {
Some(n) => {
@ -1694,10 +1694,10 @@ impl Expr<'_> {
}
}
// Whether this looks like a place expr, without checking for deref
// adjustments.
// This will return `true` in some potentially surprising cases such as
// `CONSTANT.field`.
/// Whether this looks like a place expr, without checking for deref
/// adjustments.
/// This will return `true` in some potentially surprising cases such as
/// `CONSTANT.field`.
pub fn is_syntactic_place_expr(&self) -> bool {
self.is_place_expr(|_| true)
}
@ -1838,7 +1838,7 @@ impl Expr<'_> {
}
}
// To a first-order approximation, is this a pattern
/// To a first-order approximation, is this a pattern?
pub fn is_approximately_pattern(&self) -> bool {
match &self.kind {
ExprKind::Box(_)
@ -2160,11 +2160,11 @@ impl fmt::Display for LoopIdError {
#[derive(Copy, Clone, Encodable, Debug, HashStable_Generic)]
pub struct Destination {
// This is `Some(_)` iff there is an explicit user-specified `label
/// This is `Some(_)` iff there is an explicit user-specified 'label
pub label: Option<Label>,
// These errors are caught and then reported during the diagnostics pass in
// librustc_passes/loops.rs
/// These errors are caught and then reported during the diagnostics pass in
/// `librustc_passes/loops.rs`
pub target_id: Result<HirId, LoopIdError>,
}
@ -2335,7 +2335,7 @@ pub enum ImplItemKind<'hir> {
Type(&'hir Ty<'hir>),
}
// The name of the associated type for `Fn` return types.
/// The name of the associated type for `Fn` return types.
pub const FN_OUTPUT_NAME: Symbol = sym::Output;
/// Bind a type to an associated type (i.e., `A = Foo`).
@ -3261,7 +3261,7 @@ pub enum ForeignItemKind<'hir> {
/// A variable captured by a closure.
#[derive(Debug, Copy, Clone, Encodable, HashStable_Generic)]
pub struct Upvar {
// First span where it is accessed (there can be multiple).
/// First span where it is accessed (there can be multiple).
pub span: Span,
}

View file

@ -850,7 +850,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
.is_some()
}
// Sets `implicitly_sized` to true on `Bounds` if necessary
/// Sets `implicitly_sized` to true on `Bounds` if necessary
pub(crate) fn add_implicitly_sized<'hir>(
&self,
bounds: &mut Bounds<'hir>,
@ -2391,7 +2391,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
path_segs
}
// Check a type `Path` and convert it to a `Ty`.
/// Check a type `Path` and convert it to a `Ty`.
pub fn res_to_ty(
&self,
opt_self_ty: Option<Ty<'tcx>>,

View file

@ -233,9 +233,10 @@ fn ensure_drop_predicates_are_implied_by_item_defn<'tcx>(
result
}
// This is an implementation of the TypeRelation trait with the
// aim of simply comparing for equality (without side-effects).
// It is not intended to be used anywhere else other than here.
/// This is an implementation of the [`TypeRelation`] trait with the
/// aim of simply comparing for equality (without side-effects).
///
/// It is not intended to be used anywhere else other than here.
pub(crate) struct SimpleEqRelation<'tcx> {
tcx: TyCtxt<'tcx>,
param_env: ty::ParamEnv<'tcx>,

View file

@ -42,22 +42,22 @@ impl<'a> fmt::Debug for VarianceTerm<'a> {
}
}
// The first pass over the crate simply builds up the set of inferreds.
/// The first pass over the crate simply builds up the set of inferreds.
pub struct TermsContext<'a, 'tcx> {
pub tcx: TyCtxt<'tcx>,
pub arena: &'a DroplessArena,
// For marker types, UnsafeCell, and other lang items where
// variance is hardcoded, records the item-id and the hardcoded
// variance.
/// For marker types, `UnsafeCell`, and other lang items where
/// variance is hardcoded, records the item-id and the hardcoded
/// variance.
pub lang_items: Vec<(LocalDefId, Vec<ty::Variance>)>,
// Maps from the node id of an item to the first inferred index
// used for its type & region parameters.
/// Maps from the node id of an item to the first inferred index
/// used for its type & region parameters.
pub inferred_starts: LocalDefIdMap<InferredIndex>,
// Maps from an InferredIndex to the term for that variable.
/// Maps from an InferredIndex to the term for that variable.
pub inferred_terms: Vec<VarianceTermPtr<'a>>,
}

View file

@ -57,8 +57,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
self.note_internal_mutation_in_method(err, expr, expected, expr_ty);
}
// Requires that the two types unify, and prints an error message if
// they don't.
/// Requires that the two types unify, and prints an error message if
/// they don't.
pub fn demand_suptype(&self, sp: Span, expected: Ty<'tcx>, actual: Ty<'tcx>) {
if let Some(mut e) = self.demand_suptype_diag(sp, expected, actual) {
e.emit();

View file

@ -79,9 +79,9 @@ impl<'a, 'tcx> Expectation<'tcx> {
}
}
// Resolves `expected` by a single level if it is a variable. If
// there is no expected type or resolution is not possible (e.g.,
// no constraints yet present), just returns `self`.
/// Resolves `expected` by a single level if it is a variable. If
/// there is no expected type or resolution is not possible (e.g.,
/// no constraints yet present), just returns `self`.
fn resolve(self, fcx: &FnCtxt<'a, 'tcx>) -> Expectation<'tcx> {
match self {
NoExpectation => NoExpectation,

View file

@ -914,8 +914,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
}
// Check if an expression `original_expr_id` comes from the condition of a while loop,
// as opposed from the body of a while loop, which we can naively check by iterating
// parents until we find a loop...
/// as opposed from the body of a while loop, which we can naively check by iterating
/// parents until we find a loop...
pub(super) fn comes_from_while_condition(
&self,
original_expr_id: HirId,

View file

@ -38,19 +38,19 @@ pub struct Inherited<'tcx> {
pub(super) fulfillment_cx: RefCell<Box<dyn TraitEngine<'tcx>>>,
// Some additional `Sized` obligations badly affect type inference.
// These obligations are added in a later stage of typeck.
// Removing these may also cause additional complications, see #101066.
/// Some additional `Sized` obligations badly affect type inference.
/// These obligations are added in a later stage of typeck.
/// Removing these may also cause additional complications, see #101066.
pub(super) deferred_sized_obligations:
RefCell<Vec<(Ty<'tcx>, Span, traits::ObligationCauseCode<'tcx>)>>,
// When we process a call like `c()` where `c` is a closure type,
// we may not have decided yet whether `c` is a `Fn`, `FnMut`, or
// `FnOnce` closure. In that case, we defer full resolution of the
// call until upvar inference can kick in and make the
// decision. We keep these deferred resolutions grouped by the
// def-id of the closure, so that once we decide, we can easily go
// back and process them.
/// When we process a call like `c()` where `c` is a closure type,
/// we may not have decided yet whether `c` is a `Fn`, `FnMut`, or
/// `FnOnce` closure. In that case, we defer full resolution of the
/// call until upvar inference can kick in and make the
/// decision. We keep these deferred resolutions grouped by the
/// def-id of the closure, so that once we decide, we can easily go
/// back and process them.
pub(super) deferred_call_resolutions: RefCell<LocalDefIdMap<Vec<DeferredCallResolution<'tcx>>>>,
pub(super) deferred_cast_checks: RefCell<Vec<super::cast::CastCheck<'tcx>>>,

View file

@ -438,9 +438,9 @@ fn expect_associated_value(tcx: TyCtxt<'_>, item: &NestedMetaItem) -> Symbol {
}
}
// A visitor that collects all #[rustc_clean] attributes from
// the HIR. It is used to verify that we really ran checks for all annotated
// nodes.
/// A visitor that collects all `#[rustc_clean]` attributes from
/// the HIR. It is used to verify that we really ran checks for all annotated
/// nodes.
pub struct FindAllAttrs<'tcx> {
tcx: TyCtxt<'tcx>,
found_attrs: Vec<&'tcx Attribute>,

View file

@ -29,10 +29,10 @@ impl<'a, 'tcx> RegionRelations<'a, 'tcx> {
#[derive(Clone, Debug)]
pub struct FreeRegionMap<'tcx> {
// Stores the relation `a < b`, where `a` and `b` are regions.
//
// Invariant: only free regions like `'x` or `'static` are stored
// in this relation, not scopes.
/// Stores the relation `a < b`, where `a` and `b` are regions.
///
/// Invariant: only free regions like `'x` or `'static` are stored
/// in this relation, not scopes.
pub(crate) relation: TransitiveRelation<Region<'tcx>>,
}

View file

@ -410,19 +410,19 @@ impl<'tcx> InferCtxt<'tcx> {
}
}
// Visitor that requires that (almost) all regions in the type visited outlive
// `least_region`. We cannot use `push_outlives_components` because regions in
// closure signatures are not included in their outlives components. We need to
// ensure all regions outlive the given bound so that we don't end up with,
// say, `ReVar` appearing in a return type and causing ICEs when other
// functions end up with region constraints involving regions from other
// functions.
//
// We also cannot use `for_each_free_region` because for closures it includes
// the regions parameters from the enclosing item.
//
// We ignore any type parameters because impl trait values are assumed to
// capture all the in-scope type parameters.
/// Visitor that requires that (almost) all regions in the type visited outlive
/// `least_region`. We cannot use `push_outlives_components` because regions in
/// closure signatures are not included in their outlives components. We need to
/// ensure all regions outlive the given bound so that we don't end up with,
/// say, `ReVar` appearing in a return type and causing ICEs when other
/// functions end up with region constraints involving regions from other
/// functions.
///
/// We also cannot use `for_each_free_region` because for closures it includes
/// the regions parameters from the enclosing item.
///
/// We ignore any type parameters because impl trait values are assumed to
/// capture all the in-scope type parameters.
pub struct ConstrainOpaqueTypeRegionVisitor<'tcx, OP: FnMut(ty::Region<'tcx>)> {
pub tcx: TyCtxt<'tcx>,
pub op: OP,

View file

@ -9,10 +9,10 @@ use super::{OpaqueTypeDecl, OpaqueTypeMap};
#[derive(Default, Debug, Clone)]
pub struct OpaqueTypeStorage<'tcx> {
// Opaque types found in explicit return types and their
// associated fresh inference variable. Writeback resolves these
// variables to get the concrete type, which can be used to
// 'de-opaque' OpaqueTypeDecl, after typeck is done with all functions.
/// Opaque types found in explicit return types and their
/// associated fresh inference variable. Writeback resolves these
/// variables to get the concrete type, which can be used to
/// 'de-opaque' OpaqueTypeDecl, after typeck is done with all functions.
pub opaque_types: OpaqueTypeMap<'tcx>,
}

View file

@ -206,7 +206,7 @@ impl LintStore {
self.late_module_passes.push(Box::new(pass));
}
// Helper method for register_early/late_pass
/// Helper method for register_early/late_pass
pub fn register_lints(&mut self, lints: &[&'static Lint]) {
for lint in lints {
self.lints.push(lint);

View file

@ -67,10 +67,10 @@ impl std::ops::Deref for MetadataBlob {
}
}
// A map from external crate numbers (as decoded from some crate file) to
// local crate numbers (as generated during this session). Each external
// crate may refer to types in other external crates, and each has their
// own crate numbers.
/// A map from external crate numbers (as decoded from some crate file) to
/// local crate numbers (as generated during this session). Each external
/// crate may refer to types in other external crates, and each has their
/// own crate numbers.
pub(crate) type CrateNumMap = IndexVec<CrateNum, CrateNum>;
pub(crate) struct CrateMetadata {

View file

@ -20,8 +20,8 @@ use super::{
/// Represents the result of const evaluation via the `eval_to_allocation` query.
#[derive(Copy, Clone, HashStable, TyEncodable, TyDecodable, Debug, Hash, Eq, PartialEq)]
pub struct ConstAlloc<'tcx> {
// the value lives here, at offset 0, and that allocation definitely is an `AllocKind::Memory`
// (so you can use `AllocMap::unwrap_memory`).
/// The value lives here, at offset 0, and that allocation definitely is an `AllocKind::Memory`
/// (so you can use `AllocMap::unwrap_memory`).
pub alloc_id: AllocId,
pub ty: Ty<'tcx>,
}

View file

@ -471,7 +471,7 @@ pub struct ImplDerivedObligationCause<'tcx> {
}
impl<'tcx> ObligationCauseCode<'tcx> {
// Return the base obligation, ignoring derived obligations.
/// Returns the base obligation, ignoring derived obligations.
pub fn peel_derives(&self) -> &Self {
let mut base_cause = self;
while let Some((parent_code, _)) = base_cause.parent() {

View file

@ -15,8 +15,8 @@ use super::{Ty, TyCtxt};
use self::BorrowKind::*;
// Captures are represented using fields inside a structure.
// This represents accessing self in the closure structure
/// Captures are represented using fields inside a structure.
/// This represents accessing self in the closure structure
pub const CAPTURE_STRUCT_LOCAL: mir::Local = mir::Local::from_u32(1);
#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, TyEncodable, TyDecodable, HashStable)]
@ -91,7 +91,7 @@ pub enum ClosureKind {
}
impl<'tcx> ClosureKind {
// This is the initial value used when doing upvar inference.
/// This is the initial value used when doing upvar inference.
pub const LATTICE_BOTTOM: ClosureKind = ClosureKind::Fn;
/// Returns `true` if a type that impls this closure kind

View file

@ -713,22 +713,24 @@ impl<'tcx> TypeckResults<'tcx> {
self.node_substs.get(&id.local_id).cloned()
}
// Returns the type of a pattern as a monotype. Like @expr_ty, this function
// doesn't provide type parameter substitutions.
/// Returns the type of a pattern as a monotype. Like [`expr_ty`], this function
/// doesn't provide type parameter substitutions.
///
/// [`expr_ty`]: TypeckResults::expr_ty
pub fn pat_ty(&self, pat: &hir::Pat<'_>) -> Ty<'tcx> {
self.node_type(pat.hir_id)
}
// Returns the type of an expression as a monotype.
//
// NB (1): This is the PRE-ADJUSTMENT TYPE for the expression. That is, in
// some cases, we insert `Adjustment` annotations such as auto-deref or
// auto-ref. The type returned by this function does not consider such
// adjustments. See `expr_ty_adjusted()` instead.
//
// NB (2): This type doesn't provide type parameter substitutions; e.g., if you
// ask for the type of "id" in "id(3)", it will return "fn(&isize) -> isize"
// instead of "fn(ty) -> T with T = isize".
/// Returns the type of an expression as a monotype.
///
/// NB (1): This is the PRE-ADJUSTMENT TYPE for the expression. That is, in
/// some cases, we insert `Adjustment` annotations such as auto-deref or
/// auto-ref. The type returned by this function does not consider such
/// adjustments. See `expr_ty_adjusted()` instead.
///
/// NB (2): This type doesn't provide type parameter substitutions; e.g., if you
/// ask for the type of `id` in `id(3)`, it will return `fn(&isize) -> isize`
/// instead of `fn(ty) -> T with T = isize`.
pub fn expr_ty(&self, expr: &hir::Expr<'_>) -> Ty<'tcx> {
self.node_type(expr.hir_id)
}
@ -995,15 +997,15 @@ impl<'tcx> CommonConsts<'tcx> {
}
}
// This struct contains information regarding the `ReFree(FreeRegion)` corresponding to a lifetime
// conflict.
/// This struct contains information regarding the `ReFree(FreeRegion)` corresponding to a lifetime
/// conflict.
#[derive(Debug)]
pub struct FreeRegionInfo {
// `LocalDefId` corresponding to FreeRegion
/// `LocalDefId` corresponding to FreeRegion
pub def_id: LocalDefId,
// the bound region corresponding to FreeRegion
/// the bound region corresponding to FreeRegion
pub boundregion: ty::BoundRegionKind,
// checks if bound region is in Impl Item
/// checks if bound region is in Impl Item
pub is_impl_item: bool,
}
@ -1660,7 +1662,7 @@ impl<'tcx> TyCtxt<'tcx> {
}
}
// Checks if the bound region is in Impl Item.
/// Checks if the bound region is in Impl Item.
pub fn is_bound_region_in_impl_item(self, suitable_region_binding_scope: LocalDefId) -> bool {
let container_id = self.parent(suitable_region_binding_scope.to_def_id());
if self.impl_trait_ref(container_id).is_some() {

View file

@ -6,7 +6,7 @@ use std::slice;
pub struct FlagComputation {
pub flags: TypeFlags,
// see `Ty::outer_exclusive_binder` for details
/// see `Ty::outer_exclusive_binder` for details
pub outer_exclusive_binder: ty::DebruijnIndex,
}

View file

@ -414,7 +414,7 @@ impl Visibility<DefId> {
self.map_id(|id| id.expect_local())
}
// Returns `true` if this item is visible anywhere in the local crate.
/// Returns `true` if this item is visible anywhere in the local crate.
pub fn is_visible_locally(self) -> bool {
match self {
Visibility::Public => true,
@ -926,9 +926,10 @@ impl<'tcx> PolyTraitPredicate<'tcx> {
}
}
/// `A: B`
#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Debug, TyEncodable, TyDecodable)]
#[derive(HashStable, TypeFoldable, TypeVisitable, Lift)]
pub struct OutlivesPredicate<A, B>(pub A, pub B); // `A: B`
pub struct OutlivesPredicate<A, B>(pub A, pub B);
pub type RegionOutlivesPredicate<'tcx> = OutlivesPredicate<ty::Region<'tcx>, ty::Region<'tcx>>;
pub type TypeOutlivesPredicate<'tcx> = OutlivesPredicate<Ty<'tcx>, ty::Region<'tcx>>;
pub type PolyRegionOutlivesPredicate<'tcx> = ty::Binder<'tcx, RegionOutlivesPredicate<'tcx>>;

View file

@ -2243,7 +2243,7 @@ impl<'tcx> Ty<'tcx> {
}
}
// If `self` is a primitive, return its [`Symbol`].
/// If `self` is a primitive, return its [`Symbol`].
pub fn primitive_symbol(self) -> Option<Symbol> {
match self.kind() {
ty::Bool => Some(sym::bool),

View file

@ -211,7 +211,7 @@ impl<'tcx> TyCtxt<'tcx> {
}
}
// Query provider for `trait_impls_of`.
/// Query provider for `trait_impls_of`.
pub(super) fn trait_impls_of_provider(tcx: TyCtxt<'_>, trait_id: DefId) -> TraitImpls {
let mut impls = TraitImpls::default();
@ -255,7 +255,7 @@ pub(super) fn trait_impls_of_provider(tcx: TyCtxt<'_>, trait_id: DefId) -> Trait
impls
}
// Query provider for `incoherent_impls`.
/// Query provider for `incoherent_impls`.
pub(super) fn incoherent_impls_provider(tcx: TyCtxt<'_>, simp: SimplifiedType) -> &[DefId] {
let mut impls = Vec::new();

View file

@ -1208,11 +1208,11 @@ pub fn is_trivially_const_drop<'tcx>(ty: Ty<'tcx>) -> bool {
}
}
// Does the equivalent of
// ```
// let v = self.iter().map(|p| p.fold_with(folder)).collect::<SmallVec<[_; 8]>>();
// folder.tcx().intern_*(&v)
// ```
/// Does the equivalent of
/// ```ignore (ilustrative)
/// let v = self.iter().map(|p| p.fold_with(folder)).collect::<SmallVec<[_; 8]>>();
/// folder.tcx().intern_*(&v)
/// ```
pub fn fold_list<'tcx, F, T>(
list: &'tcx ty::List<T>,
folder: &mut F,

View file

@ -2,35 +2,35 @@ use rustc_middle::thir::*;
#[derive(Debug, PartialEq)]
pub(crate) enum Category {
// An assignable memory location like `x`, `x.f`, `foo()[3]`, that
// sort of thing. Something that could appear on the LHS of an `=`
// sign.
/// An assignable memory location like `x`, `x.f`, `foo()[3]`, that
/// sort of thing. Something that could appear on the LHS of an `=`
/// sign.
Place,
// A literal like `23` or `"foo"`. Does not include constant
// expressions like `3 + 5`.
/// A literal like `23` or `"foo"`. Does not include constant
/// expressions like `3 + 5`.
Constant,
// Something that generates a new value at runtime, like `x + y`
// or `foo()`.
/// Something that generates a new value at runtime, like `x + y`
/// or `foo()`.
Rvalue(RvalueFunc),
}
// Rvalues fall into different "styles" that will determine which fn
// is best suited to generate them.
/// Rvalues fall into different "styles" that will determine which fn
/// is best suited to generate them.
#[derive(Debug, PartialEq)]
pub(crate) enum RvalueFunc {
// Best generated by `into`. This is generally exprs that
// cause branching, like `match`, but also includes calls.
/// Best generated by `into`. This is generally exprs that
/// cause branching, like `match`, but also includes calls.
Into,
// Best generated by `as_rvalue`. This is usually the case.
/// Best generated by `as_rvalue`. This is usually the case.
AsRvalue,
}
/// Determines the category for a given expression. Note that scope
/// and paren expressions have no category.
impl Category {
/// Determines the category for a given expression. Note that scope
/// and paren expressions have no category.
pub(crate) fn of(ek: &ExprKind<'_>) -> Option<Category> {
match *ek {
ExprKind::Scope { .. } => None,

View file

@ -34,8 +34,8 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
Operand::Constant(constant)
}
// Returns a zero literal operand for the appropriate type, works for
// bool, char and integers.
/// Returns a zero literal operand for the appropriate type, works for
/// bool, char and integers.
pub(crate) fn zero_literal(&mut self, span: Span, ty: Ty<'tcx>) -> Operand<'tcx> {
let literal = ConstantKind::from_bits(self.tcx, 0, ty::ParamEnv::empty().and(ty));

View file

@ -443,8 +443,9 @@ impl<'tcx> Scopes<'tcx> {
impl<'a, 'tcx> Builder<'a, 'tcx> {
// Adding and removing scopes
// ==========================
// Start a breakable scope, which tracks where `continue`, `break` and
// `return` should branch to.
/// Start a breakable scope, which tracks where `continue`, `break` and
/// `return` should branch to.
pub(crate) fn in_breakable_scope<F>(
&mut self,
loop_block: Option<BasicBlock>,
@ -799,6 +800,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
// Finding scopes
// ==============
/// Returns the scope that we should use as the lifetime of an
/// operand. Basically, an operand must live until it is consumed.
/// This is similar to, but not quite the same as, the temporary
@ -824,6 +826,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
// Scheduling drops
// ================
pub(crate) fn schedule_drop_storage_and_value(
&mut self,
span: Span,
@ -996,6 +999,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
// Other
// =====
/// Returns the [DropIdx] for the innermost drop if the function unwound at
/// this point. The `DropIdx` will be created if it doesn't already exist.
fn diverge_cleanup(&mut self) -> DropIdx {

View file

@ -5,37 +5,36 @@ use crate::util;
use crate::MirPass;
use rustc_middle::mir::patch::MirPatch;
// This pass moves values being dropped that are within a packed
// struct to a separate local before dropping them, to ensure that
// they are dropped from an aligned address.
//
// For example, if we have something like
// ```Rust
// #[repr(packed)]
// struct Foo {
// dealign: u8,
// data: Vec<u8>
// }
//
// let foo = ...;
// ```
//
// We want to call `drop_in_place::<Vec<u8>>` on `data` from an aligned
// address. This means we can't simply drop `foo.data` directly, because
// its address is not aligned.
//
// Instead, we move `foo.data` to a local and drop that:
// ```
// storage.live(drop_temp)
// drop_temp = foo.data;
// drop(drop_temp) -> next
// next:
// storage.dead(drop_temp)
// ```
//
// The storage instructions are required to avoid stack space
// blowup.
/// This pass moves values being dropped that are within a packed
/// struct to a separate local before dropping them, to ensure that
/// they are dropped from an aligned address.
///
/// For example, if we have something like
/// ```ignore (ilustrative)
/// #[repr(packed)]
/// struct Foo {
/// dealign: u8,
/// data: Vec<u8>
/// }
///
/// let foo = ...;
/// ```
///
/// We want to call `drop_in_place::<Vec<u8>>` on `data` from an aligned
/// address. This means we can't simply drop `foo.data` directly, because
/// its address is not aligned.
///
/// Instead, we move `foo.data` to a local and drop that:
/// ```ignore (ilustrative)
/// storage.live(drop_temp)
/// drop_temp = foo.data;
/// drop(drop_temp) -> next
/// next:
/// storage.dead(drop_temp)
/// ```
///
/// The storage instructions are required to avoid stack space
/// blowup.
pub struct AddMovesForPackedDrops;
impl<'tcx> MirPass<'tcx> for AddMovesForPackedDrops {

View file

@ -25,7 +25,7 @@ pub fn build_ptr_tys<'tcx>(
(unique_ty, nonnull_ty, ptr_ty)
}
// Constructs the projection needed to access a Box's pointer
/// Constructs the projection needed to access a Box's pointer
pub fn build_projection<'tcx>(
unique_ty: Ty<'tcx>,
nonnull_ty: Ty<'tcx>,

View file

@ -295,8 +295,8 @@ impl<'tcx> InliningMap<'tcx> {
assert!(self.index.insert(source, start_index..end_index).is_none());
}
// Internally iterate over all items referenced by `source` which will be
// made available for inlining.
/// Internally iterate over all items referenced by `source` which will be
/// made available for inlining.
pub fn with_inlining_candidates<F>(&self, source: MonoItem<'tcx>, mut f: F)
where
F: FnMut(MonoItem<'tcx>),
@ -310,7 +310,7 @@ impl<'tcx> InliningMap<'tcx> {
}
}
// Internally iterate over all items and the things each accesses.
/// Internally iterate over all items and the things each accesses.
pub fn iter_accesses<F>(&self, mut f: F)
where
F: FnMut(MonoItem<'tcx>, &[MonoItem<'tcx>]),

View file

@ -1,5 +1,5 @@
// Characters and their corresponding confusables were collected from
// https://www.unicode.org/Public/security/10.0.0/confusables.txt
//! Characters and their corresponding confusables were collected from
//! <https://www.unicode.org/Public/security/10.0.0/confusables.txt>
use super::StringReader;
use crate::token::{self, Delimiter};

View file

@ -50,7 +50,7 @@ impl AttrWrapper {
self.attrs
}
// Prepend `self.attrs` to `attrs`.
/// Prepend `self.attrs` to `attrs`.
// FIXME: require passing an NT to prevent misuse of this method
pub(crate) fn prepend_to_nt_inner(self, attrs: &mut AttrVec) {
let mut self_attrs = self.attrs;

View file

@ -224,9 +224,9 @@ impl MultiSugg {
}
}
// SnapshotParser is used to create a snapshot of the parser
// without causing duplicate errors being emitted when the `Parser`
// is dropped.
/// SnapshotParser is used to create a snapshot of the parser
/// without causing duplicate errors being emitted when the `Parser`
/// is dropped.
pub struct SnapshotParser<'a> {
parser: Parser<'a>,
unclosed_delims: Vec<UnmatchedBrace>,

View file

@ -779,26 +779,26 @@ impl<K: DepKind> DepGraph<K> {
}
}
// Returns true if the given node has been marked as red during the
// current compilation session. Used in various assertions
/// Returns true if the given node has been marked as red during the
/// current compilation session. Used in various assertions
pub fn is_red(&self, dep_node: &DepNode<K>) -> bool {
self.node_color(dep_node) == Some(DepNodeColor::Red)
}
// Returns true if the given node has been marked as green during the
// current compilation session. Used in various assertions
/// Returns true if the given node has been marked as green during the
/// current compilation session. Used in various assertions
pub fn is_green(&self, dep_node: &DepNode<K>) -> bool {
self.node_color(dep_node).map_or(false, |c| c.is_green())
}
// This method loads all on-disk cacheable query results into memory, so
// they can be written out to the new cache file again. Most query results
// will already be in memory but in the case where we marked something as
// green but then did not need the value, that value will never have been
// loaded from disk.
//
// This method will only load queries that will end up in the disk cache.
// Other queries will not be executed.
/// This method loads all on-disk cacheable query results into memory, so
/// they can be written out to the new cache file again. Most query results
/// will already be in memory but in the case where we marked something as
/// green but then did not need the value, that value will never have been
/// loaded from disk.
///
/// This method will only load queries that will end up in the disk cache.
/// Other queries will not be executed.
pub fn exec_cache_promotions<Tcx: DepContext<DepKind = K>>(&self, tcx: Tcx) {
let _prof_timer = tcx.profiler().generic_activity("incr_comp_query_cache_promotion");

View file

@ -196,7 +196,7 @@ pub(crate) struct NameResolution<'a> {
}
impl<'a> NameResolution<'a> {
// Returns the binding for the name if it is known or None if it not known.
/// Returns the binding for the name if it is known or None if it not known.
pub(crate) fn binding(&self) -> Option<&'a NameBinding<'a>> {
self.binding.and_then(|binding| {
if !binding.is_glob_import() || self.single_imports.is_empty() {
@ -228,8 +228,8 @@ fn pub_use_of_private_extern_crate_hack(import: &Import<'_>, binding: &NameBindi
}
impl<'a> Resolver<'a> {
// Given a binding and an import that resolves to it,
// return the corresponding binding defined by the import.
/// Given a binding and an import that resolves to it,
/// return the corresponding binding defined by the import.
pub(crate) fn import(
&self,
binding: &'a NameBinding<'a>,
@ -261,7 +261,7 @@ impl<'a> Resolver<'a> {
})
}
// Define the name or return the existing binding if there is a collision.
/// Define the name or return the existing binding if there is a collision.
pub(crate) fn try_define(
&mut self,
module: Module<'a>,

View file

@ -94,7 +94,7 @@ impl<'tcx> SaveContext<'tcx> {
}
}
// Returns path to the compilation output (e.g., libfoo-12345678.rmeta)
/// Returns path to the compilation output (e.g., libfoo-12345678.rmeta)
pub fn compilation_output(&self, crate_name: &str) -> PathBuf {
let sess = &self.tcx.sess;
// Save-analysis is emitted per whole session, not per each crate type
@ -112,7 +112,7 @@ impl<'tcx> SaveContext<'tcx> {
}
}
// List external crates used by the current crate.
/// List external crates used by the current crate.
pub fn get_external_crates(&self) -> Vec<ExternalCrateData> {
let mut result = Vec::with_capacity(self.tcx.crates(()).len());

View file

@ -7,7 +7,7 @@ macro_rules! max_leb128_len {
};
}
// Returns the longest LEB128 encoding of all supported integer types.
/// Returns the longest LEB128 encoding of all supported integer types.
pub const fn max_leb128_len() -> usize {
max_leb128_len!(u128)
}

View file

@ -155,19 +155,19 @@ impl Encoder for MemEncoder {
pub type FileEncodeResult = Result<usize, io::Error>;
// `FileEncoder` encodes data to file via fixed-size buffer.
//
// When encoding large amounts of data to a file, using `FileEncoder` may be
// preferred over using `MemEncoder` to encode to a `Vec`, and then writing the
// `Vec` to file, as the latter uses as much memory as there is encoded data,
// while the former uses the fixed amount of memory allocated to the buffer.
// `FileEncoder` also has the advantage of not needing to reallocate as data
// is appended to it, but the disadvantage of requiring more error handling,
// which has some runtime overhead.
/// `FileEncoder` encodes data to file via fixed-size buffer.
///
/// When encoding large amounts of data to a file, using `FileEncoder` may be
/// preferred over using `MemEncoder` to encode to a `Vec`, and then writing the
/// `Vec` to file, as the latter uses as much memory as there is encoded data,
/// while the former uses the fixed amount of memory allocated to the buffer.
/// `FileEncoder` also has the advantage of not needing to reallocate as data
/// is appended to it, but the disadvantage of requiring more error handling,
/// which has some runtime overhead.
pub struct FileEncoder {
// The input buffer. For adequate performance, we need more control over
// buffering than `BufWriter` offers. If `BufWriter` ever offers a raw
// buffer access API, we can use it, and remove `buf` and `buffered`.
/// The input buffer. For adequate performance, we need more control over
/// buffering than `BufWriter` offers. If `BufWriter` ever offers a raw
/// buffer access API, we can use it, and remove `buf` and `buffered`.
buf: Box<[MaybeUninit<u8>]>,
buffered: usize,
flushed: usize,
@ -711,7 +711,7 @@ impl<'a> Decodable<MemDecoder<'a>> for Vec<u8> {
}
}
// An integer that will always encode to 8 bytes.
/// An integer that will always encode to 8 bytes.
pub struct IntEncodedWithFixedSize(pub u64);
impl IntEncodedWithFixedSize {

View file

@ -78,10 +78,10 @@ use sha2::Sha256;
#[cfg(test)]
mod tests;
// Per-session global variables: this struct is stored in thread-local storage
// in such a way that it is accessible without any kind of handle to all
// threads within the compilation session, but is not accessible outside the
// session.
/// Per-session global variables: this struct is stored in thread-local storage
/// in such a way that it is accessible without any kind of handle to all
/// threads within the compilation session, but is not accessible outside the
/// session.
pub struct SessionGlobals {
symbol_interner: symbol::Interner,
span_interner: Lock<span_encoding::SpanInterner>,
@ -359,8 +359,8 @@ impl FileName {
FileNameDisplay { inner: self, display_pref: FileNameDisplayPreference::Remapped }
}
// This may include transient local filesystem information.
// Must not be embedded in build outputs.
/// This may include transient local filesystem information.
/// Must not be embedded in build outputs.
pub fn prefer_local(&self) -> FileNameDisplay<'_> {
FileNameDisplay { inner: self, display_pref: FileNameDisplayPreference::Local }
}
@ -751,7 +751,7 @@ impl Span {
/// Checks if a span is "internal" to a macro in which `unsafe`
/// can be used without triggering the `unsafe_code` lint.
// (that is, a macro marked with `#[allow_internal_unsafe]`).
/// (that is, a macro marked with `#[allow_internal_unsafe]`).
pub fn allows_unsafe(self) -> bool {
self.ctxt().outer_expn_data().allow_internal_unsafe
}

View file

@ -130,14 +130,14 @@ impl FileLoader for RealFileLoader {
/// different has no real downsides.
#[derive(Copy, Clone, PartialEq, Eq, Hash, Encodable, Decodable, Debug)]
pub struct StableSourceFileId {
// A hash of the source file's FileName. This is hash so that it's size
// is more predictable than if we included the actual FileName value.
/// A hash of the source file's [`FileName`]. This is hash so that it's size
/// is more predictable than if we included the actual [`FileName`] value.
pub file_name_hash: u64,
// The CrateNum of the crate this source file was originally parsed for.
// We cannot include this information in the hash because at the time
// of hashing we don't have the context to map from the CrateNum's numeric
// value to a StableCrateId.
/// The [`CrateNum`] of the crate this source file was originally parsed for.
/// We cannot include this information in the hash because at the time
/// of hashing we don't have the context to map from the [`CrateNum`]'s numeric
/// value to a `StableCrateId`.
pub cnum: CrateNum,
}
@ -402,7 +402,7 @@ impl SourceMap {
source_file
}
// If there is a doctest offset, applies it to the line.
/// If there is a doctest offset, applies it to the line.
pub fn doctest_offset_line(&self, file: &FileName, orig: usize) -> usize {
match file {
FileName::DocTest(_, offset) => {
@ -429,7 +429,7 @@ impl SourceMap {
Loc { file: sf, line, col, col_display }
}
// If the corresponding `SourceFile` is empty, does not return a line number.
/// If the corresponding `SourceFile` is empty, does not return a line number.
pub fn lookup_line(&self, pos: BytePos) -> Result<SourceFileAndLine, Lrc<SourceFile>> {
let f = self.lookup_source_file(pos);
@ -1053,9 +1053,9 @@ impl SourceMap {
SourceFileAndBytePos { sf, pos: offset }
}
// Returns the index of the `SourceFile` (in `self.files`) that contains `pos`.
// This index is guaranteed to be valid for the lifetime of this `SourceMap`,
// since `source_files` is a `MonotonicVec`
/// Returns the index of the [`SourceFile`] (in `self.files`) that contains `pos`.
/// This index is guaranteed to be valid for the lifetime of this `SourceMap`,
/// since `source_files` is a `MonotonicVec`
pub fn lookup_source_file_idx(&self, pos: BytePos) -> usize {
self.files
.borrow()

View file

@ -2051,8 +2051,8 @@ impl Symbol {
}
impl Ident {
// Returns `true` for reserved identifiers used internally for elided lifetimes,
// unnamed method parameters, crate root module, error recovery etc.
/// Returns `true` for reserved identifiers used internally for elided lifetimes,
/// unnamed method parameters, crate root module, error recovery etc.
pub fn is_special(self) -> bool {
self.name.is_special()
}

View file

@ -1650,9 +1650,9 @@ pub struct TargetOptions {
/// Flag indicating whether #[thread_local] is available for this target.
pub has_thread_local: bool,
// This is mainly for easy compatibility with emscripten.
// If we give emcc .o files that are actually .bc files it
// will 'just work'.
/// This is mainly for easy compatibility with emscripten.
/// If we give emcc .o files that are actually .bc files it
/// will 'just work'.
pub obj_is_bitcode: bool,
/// Whether the target requires that emitted object code includes bitcode.
pub forces_embed_bitcode: bool,
@ -1792,12 +1792,12 @@ pub struct TargetOptions {
/// since this is most common among tier 1 and tier 2 targets.
pub supports_stack_protector: bool,
// The name of entry function.
// Default value is "main"
/// The name of entry function.
/// Default value is "main"
pub entry_name: StaticCow<str>,
// The ABI of entry function.
// Default value is `Conv::C`, i.e. C call convention
/// The ABI of entry function.
/// Default value is `Conv::C`, i.e. C call convention
pub entry_abi: Conv,
}

View file

@ -861,7 +861,7 @@ impl<'tcx> AutoTraitFinder<'tcx> {
}
}
// Replaces all ReVars in a type with ty::Region's, using the provided map
/// Replaces all ReVars in a type with ty::Region's, using the provided map
pub struct RegionReplacer<'a, 'tcx> {
vid_to_region: &'a FxHashMap<ty::RegionVid, ty::Region<'tcx>>,
tcx: TyCtxt<'tcx>,

View file

@ -829,7 +829,7 @@ impl<'tcx> TypeFolder<'tcx> for BoundVarReplacer<'_, 'tcx> {
}
}
// The inverse of `BoundVarReplacer`: replaces placeholders with the bound vars from which they came.
/// The inverse of [`BoundVarReplacer`]: replaces placeholders with the bound vars from which they came.
pub struct PlaceholderReplacer<'me, 'tcx> {
infcx: &'me InferCtxt<'tcx>,
mapped_regions: BTreeMap<ty::PlaceholderRegion, ty::BoundRegion>,

View file

@ -230,7 +230,7 @@ fn fulfill_implication<'tcx>(
Ok(infcx.resolve_vars_if_possible(target_substs))
}
// Query provider for `specialization_graph_of`.
/// Query provider for `specialization_graph_of`.
pub(super) fn specialization_graph_provider(
tcx: TyCtxt<'_>,
trait_id: DefId,

View file

@ -115,7 +115,6 @@ impl From<DefId> for ItemId {
#[derive(Clone, Debug)]
pub(crate) struct Crate {
pub(crate) module: Item,
pub(crate) primitives: ThinVec<(DefId, PrimitiveType)>,
/// Only here so that they can be filtered through the rustdoc passes.
pub(crate) external_traits: Rc<RefCell<FxHashMap<DefId, Trait>>>,
}
@ -2572,7 +2571,7 @@ mod size_asserts {
use super::*;
use rustc_data_structures::static_assert_size;
// tidy-alphabetical-start
static_assert_size!(Crate, 72); // frequently moved by-value
static_assert_size!(Crate, 64); // frequently moved by-value
static_assert_size!(DocFragment, 32);
static_assert_size!(GenericArg, 32);
static_assert_size!(GenericArgs, 32);

View file

@ -73,7 +73,7 @@ pub(crate) fn krate(cx: &mut DocContext<'_>) -> Crate {
}));
}
Crate { module, primitives, external_traits: cx.external_traits.clone() }
Crate { module, external_traits: cx.external_traits.clone() }
}
pub(crate) fn substs_to_args<'tcx>(

View file

@ -8,7 +8,7 @@ use crate::formats::cache::Cache;
use crate::visit::DocVisitor;
use rustc_data_structures::fx::{FxHashMap, FxHashSet};
use rustc_hir::def_id::DefId;
use rustc_hir::def_id::{DefId, LOCAL_CRATE};
use rustc_middle::ty::{self, DefIdTree};
use rustc_span::symbol::sym;
@ -25,7 +25,9 @@ pub(crate) fn collect_trait_impls(mut krate: Crate, cx: &mut DocContext<'_>) ->
synth.impls
});
let prims: FxHashSet<PrimitiveType> = krate.primitives.iter().map(|p| p.1).collect();
let local_crate = ExternalCrate { crate_num: LOCAL_CRATE };
let prims: FxHashSet<PrimitiveType> =
local_crate.primitives(cx.tcx).iter().map(|p| p.1).collect();
let crate_items = {
let mut coll = ItemCollector::new();

View file

@ -54,23 +54,35 @@ compare-elements-position-near: (".block.keyword li:nth-child(1)", ".mobile-topb
// Now checking the background color of the sidebar.
show-text: true
local-storage: {"rustdoc-use-system-theme": "false", "rustdoc-theme": "dark"}
reload:
// Open the sidebar menu.
click: ".sidebar-menu-toggle"
assert-css: (".sidebar", {"background-color": "rgb(80, 80, 80)", "color": "rgb(221, 221, 221)"})
define-function: (
"check-colors",
(theme, color, background),
[
("local-storage", {"rustdoc-use-system-theme": "false", "rustdoc-theme": |theme|}),
("reload"),
local-storage: {"rustdoc-use-system-theme": "false", "rustdoc-theme": "ayu"}
reload:
// Open the sidebar menu.
("click", ".sidebar-menu-toggle"),
("assert-css", (".sidebar", {
"background-color": |background|,
"color": |color|,
})),
],
)
// Open the sidebar menu.
click: ".sidebar-menu-toggle"
assert-css: (".sidebar", {"background-color": "rgb(20, 25, 31)", "color": "rgb(197, 197, 197)"})
local-storage: {"rustdoc-use-system-theme": "false", "rustdoc-theme": "light"}
reload:
// Open the sidebar menu.
click: ".sidebar-menu-toggle"
assert-css: (".sidebar", {"background-color": "rgb(245, 245, 245)", "color": "rgb(0, 0, 0)"})
call-function: ("check-colors", {
"theme": "ayu",
"color": "rgb(197, 197, 197)",
"background": "rgb(20, 25, 31)",
})
call-function: ("check-colors", {
"theme": "dark",
"color": "rgb(221, 221, 221)",
"background": "rgb(80, 80, 80)",
})
call-function: ("check-colors", {
"theme": "light",
"color": "rgb(0, 0, 0)",
"background": "rgb(245, 245, 245)",
})

View file

@ -0,0 +1,15 @@
#![crate_name = "foo"]
// @has 'foo/struct.Foo.html'
// @has - '//*[@id="deref-methods-i32"]' 'Methods from Deref<Target = i32>'
// @has - '//*[@id="deref-methods-i32-1"]//*[@id="associatedconstant.BITS"]/h4' \
// 'pub const BITS: u32 = 32u32'
pub struct Foo(i32);
impl std::ops::Deref for Foo {
type Target = i32;
fn deref(&self) -> &Self::Target {
&self.0
}
}

View file

@ -296,6 +296,13 @@ needed.
### Exporting changes to the rustc repo
Keep in mind that pushing is the most complicated job that josh has to do --
pulling just filters the rustc history, but pushing needs to construct a new
rustc history that would filter to the given Miri history! To avoid problems, it
is a good idea to always pull immediately before you push. In particular, you
should never do two josh pushes without an intermediate pull; that can lead to
duplicated commits.
Josh needs to be running, as described above. We will use the josh proxy to push
to your fork of rustc. Run the following in the Miri repo, assuming we are on an
up-to-date master branch:

View file

@ -281,9 +281,10 @@ pub fn phase_rustc(mut args: impl Iterator<Item = String>, phase: RustcPhase) {
eprintln!("[cargo-miri rustc] writing run info to `{}`", filename.display());
}
info.store(&filename);
// For Windows, do the same thing again with `.exe` appended to the filename.
// For Windows and WASM, do the same thing again with `.exe`/`.wasm` appended to the filename.
// (Need to do this here as cargo moves that "binary" to a different place before running it.)
info.store(&out_filename("", ".exe"));
info.store(&out_filename("", ".wasm"));
};
let runnable_crate = !info_query && is_runnable_crate();

View file

@ -1,6 +1,17 @@
#!/bin/bash
set -euo pipefail
set -x
function begingroup {
echo "::group::$@"
set -x
}
function endgroup {
set +x
echo "::endgroup"
}
begingroup "Building Miri"
# Determine configuration for installed build
echo "Installing release version of Miri"
@ -14,14 +25,15 @@ export CARGO_EXTRA_FLAGS="--locked"
./miri check --no-default-features # make sure this can be built
./miri check --all-features # and this, too
./miri build --all-targets # the build that all the `./miri test` below will use
echo
endgroup
# Test
function run_tests {
if [ -n "${MIRI_TEST_TARGET+exists}" ]; then
echo "Testing foreign architecture $MIRI_TEST_TARGET"
begingroup "Testing foreign architecture $MIRI_TEST_TARGET"
else
echo "Testing host architecture"
begingroup "Testing host architecture"
fi
## ui test suite
@ -52,7 +64,6 @@ function run_tests {
echo 'build.rustc-wrapper = "thisdoesnotexist"' > .cargo/config.toml
# Run the actual test
${PYTHON} test-cargo-miri/run-test.py
echo
# Clean up
unset RUSTC MIRI
rm -rf .cargo
@ -63,16 +74,23 @@ function run_tests {
cargo miri run --manifest-path bench-cargo-miri/$BENCH/Cargo.toml
done
fi
endgroup
}
function run_tests_minimal {
if [ -n "${MIRI_TEST_TARGET+exists}" ]; then
echo "Testing MINIMAL foreign architecture $MIRI_TEST_TARGET: only testing $@"
begingroup "Testing MINIMAL foreign architecture $MIRI_TEST_TARGET: only testing $@"
else
echo "Testing MINIMAL host architecture: only testing $@"
begingroup "Testing MINIMAL host architecture: only testing $@"
fi
./miri test -- "$@"
# Ensure that a small smoke test of cargo-miri works.
cargo miri run --manifest-path test-cargo-miri/no-std-smoke/Cargo.toml --target ${MIRI_TEST_TARGET-$HOST_TARGET}
endgroup
}
# host
@ -85,6 +103,7 @@ case $HOST_TARGET in
MIRI_TEST_TARGET=i686-pc-windows-msvc run_tests
MIRI_TEST_TARGET=x86_64-unknown-freebsd run_tests_minimal hello integer vec panic/panic concurrency/simple atomic data_race env/var
MIRI_TEST_TARGET=aarch64-linux-android run_tests_minimal hello integer vec panic/panic
MIRI_TEST_TARGET=wasm32-wasi MIRI_NO_STD=1 run_tests_minimal no_std # supports std but miri doesn't support it
MIRI_TEST_TARGET=thumbv7em-none-eabihf MIRI_NO_STD=1 run_tests_minimal no_std # no_std embedded architecture
;;
x86_64-apple-darwin)

View file

@ -1 +1 @@
7477c1f4f7d6bef037d523099b240d22aa1b63a0
454784afba5bf35b5ff14ada0e31265ad1d75e73

View file

@ -838,18 +838,18 @@ impl VClockAlloc {
&self,
alloc_id: AllocId,
range: AllocRange,
global: &GlobalState,
thread_mgr: &ThreadManager<'_, '_>,
machine: &MiriMachine<'_, '_>,
) -> InterpResult<'tcx> {
let global = machine.data_race.as_ref().unwrap();
if global.race_detecting() {
let (index, clocks) = global.current_thread_state(thread_mgr);
let (index, clocks) = global.current_thread_state(&machine.threads);
let mut alloc_ranges = self.alloc_ranges.borrow_mut();
for (offset, range) in alloc_ranges.iter_mut(range.start, range.size) {
if let Err(DataRace) = range.read_race_detect(&clocks, index) {
// Report data-race.
return Self::report_data_race(
global,
thread_mgr,
&machine.threads,
range,
"Read",
false,
@ -869,17 +869,17 @@ impl VClockAlloc {
alloc_id: AllocId,
range: AllocRange,
write_type: WriteType,
global: &mut GlobalState,
thread_mgr: &ThreadManager<'_, '_>,
machine: &mut MiriMachine<'_, '_>,
) -> InterpResult<'tcx> {
let global = machine.data_race.as_mut().unwrap();
if global.race_detecting() {
let (index, clocks) = global.current_thread_state(thread_mgr);
let (index, clocks) = global.current_thread_state(&machine.threads);
for (offset, range) in self.alloc_ranges.get_mut().iter_mut(range.start, range.size) {
if let Err(DataRace) = range.write_race_detect(&clocks, index, write_type) {
// Report data-race
return Self::report_data_race(
global,
thread_mgr,
&machine.threads,
range,
write_type.get_descriptor(),
false,
@ -901,10 +901,9 @@ impl VClockAlloc {
&mut self,
alloc_id: AllocId,
range: AllocRange,
global: &mut GlobalState,
thread_mgr: &ThreadManager<'_, '_>,
machine: &mut MiriMachine<'_, '_>,
) -> InterpResult<'tcx> {
self.unique_access(alloc_id, range, WriteType::Write, global, thread_mgr)
self.unique_access(alloc_id, range, WriteType::Write, machine)
}
/// Detect data-races for an unsynchronized deallocate operation, will not perform
@ -915,10 +914,9 @@ impl VClockAlloc {
&mut self,
alloc_id: AllocId,
range: AllocRange,
global: &mut GlobalState,
thread_mgr: &ThreadManager<'_, '_>,
machine: &mut MiriMachine<'_, '_>,
) -> InterpResult<'tcx> {
self.unique_access(alloc_id, range, WriteType::Deallocate, global, thread_mgr)
self.unique_access(alloc_id, range, WriteType::Deallocate, machine)
}
}

View file

@ -118,6 +118,13 @@ pub struct Thread<'mir, 'tcx> {
/// The virtual call stack.
stack: Vec<Frame<'mir, 'tcx, Provenance, FrameData<'tcx>>>,
/// The index of the topmost user-relevant frame in `stack`. This field must contain
/// the value produced by `get_top_user_relevant_frame`.
/// The `None` state here represents
/// This field is a cache to reduce how often we call that method. The cache is manually
/// maintained inside `MiriMachine::after_stack_push` and `MiriMachine::after_stack_pop`.
top_user_relevant_frame: Option<usize>,
/// The join status.
join_status: ThreadJoinStatus,
@ -147,6 +154,40 @@ impl<'mir, 'tcx> Thread<'mir, 'tcx> {
fn thread_name(&self) -> &[u8] {
if let Some(ref thread_name) = self.thread_name { thread_name } else { b"<unnamed>" }
}
/// Return the top user-relevant frame, if there is one.
/// Note that the choice to return `None` here when there is no user-relevant frame is part of
/// justifying the optimization that only pushes of user-relevant frames require updating the
/// `top_user_relevant_frame` field.
fn compute_top_user_relevant_frame(&self) -> Option<usize> {
self.stack
.iter()
.enumerate()
.rev()
.find_map(|(idx, frame)| if frame.extra.is_user_relevant { Some(idx) } else { None })
}
/// Re-compute the top user-relevant frame from scratch.
pub fn recompute_top_user_relevant_frame(&mut self) {
self.top_user_relevant_frame = self.compute_top_user_relevant_frame();
}
/// Set the top user-relevant frame to the given value. Must be equal to what
/// `get_top_user_relevant_frame` would return!
pub fn set_top_user_relevant_frame(&mut self, frame_idx: usize) {
debug_assert_eq!(Some(frame_idx), self.compute_top_user_relevant_frame());
self.top_user_relevant_frame = Some(frame_idx);
}
/// Returns the topmost frame that is considered user-relevant, or the
/// top of the stack if there is no such frame, or `None` if the stack is empty.
pub fn top_user_relevant_frame(&self) -> Option<usize> {
debug_assert_eq!(self.top_user_relevant_frame, self.compute_top_user_relevant_frame());
// This can be called upon creation of an allocation. We create allocations while setting up
// parts of the Rust runtime when we do not have any stack frames yet, so we need to handle
// empty stacks.
self.top_user_relevant_frame.or_else(|| self.stack.len().checked_sub(1))
}
}
impl<'mir, 'tcx> std::fmt::Debug for Thread<'mir, 'tcx> {
@ -167,6 +208,7 @@ impl<'mir, 'tcx> Default for Thread<'mir, 'tcx> {
state: ThreadState::Enabled,
thread_name: None,
stack: Vec::new(),
top_user_relevant_frame: None,
join_status: ThreadJoinStatus::Joinable,
panic_payload: None,
last_error: None,
@ -184,8 +226,15 @@ impl<'mir, 'tcx> Thread<'mir, 'tcx> {
impl VisitTags for Thread<'_, '_> {
fn visit_tags(&self, visit: &mut dyn FnMut(SbTag)) {
let Thread { panic_payload, last_error, stack, state: _, thread_name: _, join_status: _ } =
self;
let Thread {
panic_payload,
last_error,
stack,
top_user_relevant_frame: _,
state: _,
thread_name: _,
join_status: _,
} = self;
panic_payload.visit_tags(visit);
last_error.visit_tags(visit);
@ -414,7 +463,7 @@ impl<'mir, 'tcx: 'mir> ThreadManager<'mir, 'tcx> {
}
/// Get a shared borrow of the currently active thread.
fn active_thread_ref(&self) -> &Thread<'mir, 'tcx> {
pub fn active_thread_ref(&self) -> &Thread<'mir, 'tcx> {
&self.threads[self.active_thread]
}

View file

@ -9,6 +9,7 @@ use std::thread;
use log::info;
use rustc_data_structures::fx::FxHashSet;
use rustc_hir::def::Namespace;
use rustc_hir::def_id::DefId;
use rustc_middle::ty::{
self,
@ -195,7 +196,7 @@ pub fn create_ecx<'mir, 'tcx: 'mir>(
MiriMachine::late_init(&mut ecx, config)?;
// Make sure we have MIR. We check MIR for some stable monomorphic function in libcore.
let sentinel = ecx.try_resolve_path(&["core", "ascii", "escape_default"]);
let sentinel = ecx.try_resolve_path(&["core", "ascii", "escape_default"], Namespace::ValueNS);
if !matches!(sentinel, Some(s) if tcx.is_mir_available(s.def.def_id())) {
tcx.sess.fatal(
"the current sysroot was built without `-Zalways-encode-mir`, or libcore seems missing. \

View file

@ -2,12 +2,12 @@ pub mod convert;
use std::cmp;
use std::iter;
use std::mem;
use std::num::NonZeroUsize;
use std::time::Duration;
use log::trace;
use rustc_hir::def::{DefKind, Namespace};
use rustc_hir::def_id::{DefId, CRATE_DEF_INDEX};
use rustc_middle::mir;
use rustc_middle::ty::{
@ -74,40 +74,67 @@ const UNIX_IO_ERROR_TABLE: &[(&str, std::io::ErrorKind)] = {
};
/// Gets an instance for a path.
fn try_resolve_did<'tcx>(tcx: TyCtxt<'tcx>, path: &[&str]) -> Option<DefId> {
tcx.crates(()).iter().find(|&&krate| tcx.crate_name(krate).as_str() == path[0]).and_then(
|krate| {
let krate = DefId { krate: *krate, index: CRATE_DEF_INDEX };
let mut items = tcx.module_children(krate);
let mut path_it = path.iter().skip(1).peekable();
///
/// A `None` namespace indicates we are looking for a module.
fn try_resolve_did(tcx: TyCtxt<'_>, path: &[&str], namespace: Option<Namespace>) -> Option<DefId> {
/// Yield all children of the given item, that have the given name.
fn find_children<'tcx: 'a, 'a>(
tcx: TyCtxt<'tcx>,
item: DefId,
name: &'a str,
) -> impl Iterator<Item = DefId> + 'a {
tcx.module_children(item)
.iter()
.filter(move |item| item.ident.name.as_str() == name)
.map(move |item| item.res.def_id())
}
while let Some(segment) = path_it.next() {
for item in mem::take(&mut items).iter() {
if item.ident.name.as_str() == *segment {
if path_it.peek().is_none() {
return Some(item.res.def_id());
}
// Take apart the path: leading crate, a sequence of modules, and potentially a final item.
let (&crate_name, path) = path.split_first().expect("paths must have at least one segment");
let (modules, item) = if let Some(namespace) = namespace {
let (&item_name, modules) =
path.split_last().expect("non-module paths must have at least 2 segments");
(modules, Some((item_name, namespace)))
} else {
(path, None)
};
items = tcx.module_children(item.res.def_id());
break;
}
}
}
None
},
)
// First find the crate.
let krate =
tcx.crates(()).iter().find(|&&krate| tcx.crate_name(krate).as_str() == crate_name)?;
let mut cur_item = DefId { krate: *krate, index: CRATE_DEF_INDEX };
// Then go over the modules.
for &segment in modules {
cur_item = find_children(tcx, cur_item, segment)
.find(|item| tcx.def_kind(item) == DefKind::Mod)?;
}
// Finally, look up the desired item in this module, if any.
match item {
Some((item_name, namespace)) =>
Some(
find_children(tcx, cur_item, item_name)
.find(|item| tcx.def_kind(item).ns() == Some(namespace))?,
),
None => Some(cur_item),
}
}
pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
/// Checks if the given crate/module exists.
fn have_module(&self, path: &[&str]) -> bool {
try_resolve_did(*self.eval_context_ref().tcx, path, None).is_some()
}
/// Gets an instance for a path; fails gracefully if the path does not exist.
fn try_resolve_path(&self, path: &[&str]) -> Option<ty::Instance<'tcx>> {
let did = try_resolve_did(self.eval_context_ref().tcx.tcx, path)?;
Some(ty::Instance::mono(self.eval_context_ref().tcx.tcx, did))
fn try_resolve_path(&self, path: &[&str], namespace: Namespace) -> Option<ty::Instance<'tcx>> {
let tcx = self.eval_context_ref().tcx.tcx;
let did = try_resolve_did(tcx, path, Some(namespace))?;
Some(ty::Instance::mono(tcx, did))
}
/// Gets an instance for a path.
fn resolve_path(&self, path: &[&str]) -> ty::Instance<'tcx> {
self.try_resolve_path(path)
fn resolve_path(&self, path: &[&str], namespace: Namespace) -> ty::Instance<'tcx> {
self.try_resolve_path(path, namespace)
.unwrap_or_else(|| panic!("failed to find required Rust item: {path:?}"))
}
@ -115,7 +142,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
/// if the path could be resolved, and None otherwise
fn eval_path_scalar(&self, path: &[&str]) -> InterpResult<'tcx, Scalar<Provenance>> {
let this = self.eval_context_ref();
let instance = this.resolve_path(path);
let instance = this.resolve_path(path, Namespace::ValueNS);
let cid = GlobalId { instance, promoted: None };
// We don't give a span -- this isn't actually used directly by the program anyway.
let const_val = this.eval_global(cid, None)?;
@ -147,7 +174,9 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
/// Helper function to get the `TyAndLayout` of a `libc` type
fn libc_ty_layout(&self, name: &str) -> InterpResult<'tcx, TyAndLayout<'tcx>> {
let this = self.eval_context_ref();
let ty = this.resolve_path(&["libc", name]).ty(*this.tcx, ty::ParamEnv::reveal_all());
let ty = this
.resolve_path(&["libc", name], Namespace::TypeNS)
.ty(*this.tcx, ty::ParamEnv::reveal_all());
this.layout_of(ty)
}
@ -155,7 +184,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
fn windows_ty_layout(&self, name: &str) -> InterpResult<'tcx, TyAndLayout<'tcx>> {
let this = self.eval_context_ref();
let ty = this
.resolve_path(&["std", "sys", "windows", "c", name])
.resolve_path(&["std", "sys", "windows", "c", name], Namespace::TypeNS)
.ty(*this.tcx, ty::ParamEnv::reveal_all());
this.layout_of(ty)
}
@ -936,31 +965,14 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
}
impl<'mir, 'tcx> MiriMachine<'mir, 'tcx> {
pub fn current_span(&self) -> CurrentSpan<'_, 'mir, 'tcx> {
CurrentSpan { current_frame_idx: None, machine: self }
}
}
/// A `CurrentSpan` should be created infrequently (ideally once) per interpreter step. It does
/// nothing on creation, but when `CurrentSpan::get` is called, searches the current stack for the
/// topmost frame which corresponds to a local crate, and returns the current span in that frame.
/// The result of that search is cached so that later calls are approximately free.
#[derive(Clone)]
pub struct CurrentSpan<'a, 'mir, 'tcx> {
current_frame_idx: Option<usize>,
machine: &'a MiriMachine<'mir, 'tcx>,
}
impl<'a, 'mir: 'a, 'tcx: 'a + 'mir> CurrentSpan<'a, 'mir, 'tcx> {
pub fn machine(&self) -> &'a MiriMachine<'mir, 'tcx> {
self.machine
}
/// Get the current span, skipping non-local frames.
/// Get the current span in the topmost function which is workspace-local and not
/// `#[track_caller]`.
/// This function is backed by a cache, and can be assumed to be very fast.
pub fn get(&mut self) -> Span {
let idx = self.current_frame_idx();
self.stack().get(idx).map(Frame::current_span).unwrap_or(rustc_span::DUMMY_SP)
/// It will work even when the stack is empty.
pub fn current_span(&self) -> Span {
self.top_user_relevant_frame()
.map(|frame_idx| self.stack()[frame_idx].current_span())
.unwrap_or(rustc_span::DUMMY_SP)
}
/// Returns the span of the *caller* of the current operation, again
@ -968,46 +980,27 @@ impl<'a, 'mir: 'a, 'tcx: 'a + 'mir> CurrentSpan<'a, 'mir, 'tcx> {
/// current operation is not in a local crate.
/// This is useful when we are processing something which occurs on function-entry and we want
/// to point at the call to the function, not the function definition generally.
pub fn get_caller(&mut self) -> Span {
pub fn caller_span(&self) -> Span {
// We need to go down at least to the caller (len - 2), or however
// far we have to go to find a frame in a local crate.
let local_frame_idx = self.current_frame_idx();
let stack = self.stack();
let idx = cmp::min(local_frame_idx, stack.len().saturating_sub(2));
stack.get(idx).map(Frame::current_span).unwrap_or(rustc_span::DUMMY_SP)
// far we have to go to find a frame in a local crate which is also not #[track_caller].
let frame_idx = self.top_user_relevant_frame().unwrap();
let frame_idx = cmp::min(frame_idx, self.stack().len().checked_sub(2).unwrap());
self.stack()[frame_idx].current_span()
}
fn stack(&self) -> &[Frame<'mir, 'tcx, Provenance, machine::FrameData<'tcx>>] {
self.machine.threads.active_thread_stack()
self.threads.active_thread_stack()
}
fn current_frame_idx(&mut self) -> usize {
*self
.current_frame_idx
.get_or_insert_with(|| Self::compute_current_frame_index(self.machine))
fn top_user_relevant_frame(&self) -> Option<usize> {
self.threads.active_thread_ref().top_user_relevant_frame()
}
// Find the position of the inner-most frame which is part of the crate being
// compiled/executed, part of the Cargo workspace, and is also not #[track_caller].
#[inline(never)]
fn compute_current_frame_index(machine: &MiriMachine<'_, '_>) -> usize {
machine
.threads
.active_thread_stack()
.iter()
.enumerate()
.rev()
.find_map(|(idx, frame)| {
let def_id = frame.instance.def_id();
if (def_id.is_local() || machine.local_crates.contains(&def_id.krate))
&& !frame.instance.def.requires_caller_location(machine.tcx)
{
Some(idx)
} else {
None
}
})
.unwrap_or(0)
/// This is the source of truth for the `is_user_relevant` flag in our `FrameExtra`.
pub fn is_user_relevant(&self, frame: &Frame<'mir, 'tcx, Provenance>) -> bool {
let def_id = frame.instance.def_id();
(def_id.is_local() || self.local_crates.contains(&def_id.krate))
&& !frame.instance.def.requires_caller_location(self.tcx)
}
}

View file

@ -97,7 +97,7 @@ pub use crate::diagnostics::{
pub use crate::eval::{
create_ecx, eval_entry, AlignmentCheck, BacktraceStyle, IsolatedOp, MiriConfig, RejectOpWith,
};
pub use crate::helpers::{CurrentSpan, EvalContextExt as _};
pub use crate::helpers::EvalContextExt as _;
pub use crate::intptrcast::ProvenanceMode;
pub use crate::machine::{
AllocExtra, FrameData, MiriInterpCx, MiriInterpCxExt, MiriMachine, MiriMemoryKind,

View file

@ -50,12 +50,18 @@ pub struct FrameData<'tcx> {
/// for the start of this frame. When we finish executing this frame,
/// we use this to register a completed event with `measureme`.
pub timing: Option<measureme::DetachedTiming>,
/// Indicates whether a `Frame` is part of a workspace-local crate and is also not
/// `#[track_caller]`. We compute this once on creation and store the result, as an
/// optimization.
/// This is used by `MiriMachine::current_span` and `MiriMachine::caller_span`
pub is_user_relevant: bool,
}
impl<'tcx> std::fmt::Debug for FrameData<'tcx> {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
// Omitting `timing`, it does not support `Debug`.
let FrameData { stacked_borrows, catch_unwind, timing: _ } = self;
let FrameData { stacked_borrows, catch_unwind, timing: _, is_user_relevant: _ } = self;
f.debug_struct("FrameData")
.field("stacked_borrows", stacked_borrows)
.field("catch_unwind", catch_unwind)
@ -65,7 +71,7 @@ impl<'tcx> std::fmt::Debug for FrameData<'tcx> {
impl VisitTags for FrameData<'_> {
fn visit_tags(&self, visit: &mut dyn FnMut(SbTag)) {
let FrameData { catch_unwind, stacked_borrows, timing: _ } = self;
let FrameData { catch_unwind, stacked_borrows, timing: _, is_user_relevant: _ } = self;
catch_unwind.visit_tags(visit);
stacked_borrows.visit_tags(visit);
@ -895,13 +901,7 @@ impl<'mir, 'tcx> Machine<'mir, 'tcx> for MiriMachine<'mir, 'tcx> {
let alloc = alloc.into_owned();
let stacks = ecx.machine.stacked_borrows.as_ref().map(|stacked_borrows| {
Stacks::new_allocation(
id,
alloc.size(),
stacked_borrows,
kind,
ecx.machine.current_span(),
)
Stacks::new_allocation(id, alloc.size(), stacked_borrows, kind, &ecx.machine)
});
let race_alloc = ecx.machine.data_race.as_ref().map(|data_race| {
data_race::AllocExtra::new_allocation(
@ -1003,22 +1003,12 @@ impl<'mir, 'tcx> Machine<'mir, 'tcx> for MiriMachine<'mir, 'tcx> {
range: AllocRange,
) -> InterpResult<'tcx> {
if let Some(data_race) = &alloc_extra.data_race {
data_race.read(
alloc_id,
range,
machine.data_race.as_ref().unwrap(),
&machine.threads,
)?;
data_race.read(alloc_id, range, machine)?;
}
if let Some(stacked_borrows) = &alloc_extra.stacked_borrows {
stacked_borrows.borrow_mut().before_memory_read(
alloc_id,
prov_extra,
range,
machine.stacked_borrows.as_ref().unwrap(),
machine.current_span(),
&machine.threads,
)?;
stacked_borrows
.borrow_mut()
.before_memory_read(alloc_id, prov_extra, range, machine)?;
}
if let Some(weak_memory) = &alloc_extra.weak_memory {
weak_memory.memory_accessed(range, machine.data_race.as_ref().unwrap());
@ -1035,22 +1025,10 @@ impl<'mir, 'tcx> Machine<'mir, 'tcx> for MiriMachine<'mir, 'tcx> {
range: AllocRange,
) -> InterpResult<'tcx> {
if let Some(data_race) = &mut alloc_extra.data_race {
data_race.write(
alloc_id,
range,
machine.data_race.as_mut().unwrap(),
&machine.threads,
)?;
data_race.write(alloc_id, range, machine)?;
}
if let Some(stacked_borrows) = &mut alloc_extra.stacked_borrows {
stacked_borrows.get_mut().before_memory_write(
alloc_id,
prov_extra,
range,
machine.stacked_borrows.as_ref().unwrap(),
machine.current_span(),
&machine.threads,
)?;
stacked_borrows.get_mut().before_memory_write(alloc_id, prov_extra, range, machine)?;
}
if let Some(weak_memory) = &alloc_extra.weak_memory {
weak_memory.memory_accessed(range, machine.data_race.as_ref().unwrap());
@ -1070,21 +1048,14 @@ impl<'mir, 'tcx> Machine<'mir, 'tcx> for MiriMachine<'mir, 'tcx> {
machine.emit_diagnostic(NonHaltingDiagnostic::FreedAlloc(alloc_id));
}
if let Some(data_race) = &mut alloc_extra.data_race {
data_race.deallocate(
alloc_id,
range,
machine.data_race.as_mut().unwrap(),
&machine.threads,
)?;
data_race.deallocate(alloc_id, range, machine)?;
}
if let Some(stacked_borrows) = &mut alloc_extra.stacked_borrows {
stacked_borrows.get_mut().before_memory_deallocation(
alloc_id,
prove_extra,
range,
machine.stacked_borrows.as_ref().unwrap(),
machine.current_span(),
&machine.threads,
machine,
)
} else {
Ok(())
@ -1126,7 +1097,9 @@ impl<'mir, 'tcx> Machine<'mir, 'tcx> for MiriMachine<'mir, 'tcx> {
stacked_borrows: stacked_borrows.map(|sb| sb.borrow_mut().new_frame(&ecx.machine)),
catch_unwind: None,
timing,
is_user_relevant: ecx.machine.is_user_relevant(&frame),
};
Ok(frame.with_extra(extra))
}
@ -1174,6 +1147,13 @@ impl<'mir, 'tcx> Machine<'mir, 'tcx> for MiriMachine<'mir, 'tcx> {
#[inline(always)]
fn after_stack_push(ecx: &mut InterpCx<'mir, 'tcx, Self>) -> InterpResult<'tcx> {
if ecx.frame().extra.is_user_relevant {
// We just pushed a local frame, so we know that the topmost local frame is the topmost
// frame. If we push a non-local frame, there's no need to do anything.
let stack_len = ecx.active_thread_stack().len();
ecx.active_thread_mut().set_top_user_relevant_frame(stack_len - 1);
}
if ecx.machine.stacked_borrows.is_some() { ecx.retag_return_place() } else { Ok(()) }
}
@ -1183,6 +1163,13 @@ impl<'mir, 'tcx> Machine<'mir, 'tcx> for MiriMachine<'mir, 'tcx> {
mut frame: Frame<'mir, 'tcx, Provenance, FrameData<'tcx>>,
unwinding: bool,
) -> InterpResult<'tcx, StackPopJump> {
if frame.extra.is_user_relevant {
// All that we store is whether or not the frame we just removed is local, so now we
// have no idea where the next topmost local frame is. So we recompute it.
// (If this ever becomes a bottleneck, we could have `push` store the previous
// user-relevant frame and restore that here.)
ecx.active_thread_mut().recompute_top_user_relevant_frame();
}
let timing = frame.extra.timing.take();
if let Some(stacked_borrows) = &ecx.machine.stacked_borrows {
stacked_borrows.borrow_mut().end_call(&frame.extra);

View file

@ -18,12 +18,12 @@ pub enum PathConversion {
}
#[cfg(unix)]
pub fn os_str_to_bytes<'a, 'tcx>(os_str: &'a OsStr) -> InterpResult<'tcx, &'a [u8]> {
pub fn os_str_to_bytes<'tcx>(os_str: &OsStr) -> InterpResult<'tcx, &[u8]> {
Ok(os_str.as_bytes())
}
#[cfg(not(unix))]
pub fn os_str_to_bytes<'a, 'tcx>(os_str: &'a OsStr) -> InterpResult<'tcx, &'a [u8]> {
pub fn os_str_to_bytes<'tcx>(os_str: &OsStr) -> InterpResult<'tcx, &[u8]> {
// On non-unix platforms the best we can do to transform bytes from/to OS strings is to do the
// intermediate transformation into strings. Which invalidates non-utf8 paths that are actually
// valid.
@ -34,11 +34,11 @@ pub fn os_str_to_bytes<'a, 'tcx>(os_str: &'a OsStr) -> InterpResult<'tcx, &'a [u
}
#[cfg(unix)]
pub fn bytes_to_os_str<'a, 'tcx>(bytes: &'a [u8]) -> InterpResult<'tcx, &'a OsStr> {
pub fn bytes_to_os_str<'tcx>(bytes: &[u8]) -> InterpResult<'tcx, &OsStr> {
Ok(OsStr::from_bytes(bytes))
}
#[cfg(not(unix))]
pub fn bytes_to_os_str<'a, 'tcx>(bytes: &'a [u8]) -> InterpResult<'tcx, &'a OsStr> {
pub fn bytes_to_os_str<'tcx>(bytes: &[u8]) -> InterpResult<'tcx, &OsStr> {
let s = std::str::from_utf8(bytes)
.map_err(|_| err_unsup_format!("{:?} is not a valid utf-8 string", bytes))?;
Ok(OsStr::new(s))

View file

@ -261,6 +261,11 @@ trait EvalContextPrivExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
// (that would be basically https://github.com/rust-lang/miri/issues/450),
// we specifically look up the static in libstd that we know is placed
// in that section.
if !this.have_module(&["std"]) {
// Looks like we are running in a `no_std` crate.
// That also means no TLS dtors callback to call.
return Ok(());
}
let thread_callback =
this.eval_windows("thread_local_key", "p_thread_callback")?.to_pointer(this)?;
let thread_callback = this.get_ptr_fn(thread_callback)?.as_instance()?;

Some files were not shown because too many files have changed in this diff Show more